package com.jpaulmorrison.graphics; import java.awt.*; import java.awt.event.*; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.*; import javax.swing.*; import javax.swing.event.*; import java.util.*; import java.util.Map.Entry; import java.io.*; import java.net.*; import javax.imageio.ImageIO; import com.jpaulmorrison.graphics.Arrow.Status; import java.lang.reflect.*; import javax.swing.filechooser.FileFilter; import javax.swing.plaf.FontUIResource; import javax.swing.text.BadLocationException; import javax.swing.text.Document; //import javax.help.*; public class DrawFBP extends JFrame implements ActionListener, ChangeListener, ComponentListener { static final long serialVersionUID = 111L; static DrawFBP driver; JLabel diagDesc; JTextField jfl = null; JTextField jfs = null; JTextField jfv = null; JLabel scaleLab; Diagram curDiag = null; File currentImageDir = null; JFrame frame; Block blockSelForDragging = null; BufferedImage buffer = null; //int maxX, maxY; Graphics2D osg; // SelectionArea area; int gFontWidth, gFontHeight; //Enclosure enclSelForDragging = null; Enclosure enclSelForArrow = null; File propertiesFile = null; HashMap<String, String> properties = null; HashMap<String, String> startProperties = null; HashMap<String, String> propertyDescriptions = null; // description is key JTabbedPaneWithCloseIcons jtp; String javaFBPJarFile = null; String jhallJarFile = null; Block selBlockM = null; // used only when mousing over Block selBlock = null; // permanent select Arrow selArrow = null; // permanent select String generalFont = null; String fixedFont = null; Font fontf = null; Font fontg = null; float defaultFontSize; GenLang defaultCompLang; double scalingFactor; //int xTranslate = 0; // 400; //int yTranslate = 0; // 400; BasicStroke bs; boolean propertiesChanged = false; ImageIcon favicon = null; // String zipFileName; int ox = 0; // enclosure being dragged - cx int oy = 0; // enclosure being dragged - cy int ow = 0; // enclosure being dragged - width int oh = 0; // enclosure being dragged - height String diagramName = null; Arrow arrowEndForDragging = null; Bend bendForDragging = null; CloseTabAction closeTabAction = null; CloseAppAction closeAppAction = null; EscapeAction escapeAction = null; KeyStroke escapeKS = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false); String blockType = Block.Types.PROCESS_BLOCK; FoundPoint arrowRoot = null; // used to draw blue circles where arrows can start int curx, cury; GenLang genLangs[]; FileChooserParms[] fCPArray = new FileChooserParms[7]; public static int CLASS = 0; public static int DIAGRAM = 1; public static int IMAGE = 2; public static int JARFILE = 3; public static int JHALL = 4; public static int PROCESS = 5; public static int GENCODE = 6; JCheckBox grid; boolean leftButton; static final int gridUnitSize = 4; // can be static - try for now static final double FORCE_VERTICAL = 10.0; // can be static as this is a // slope static final double FORCE_HORIZONTAL = 0.1; // can be static as this is a // slope static final int REG_CREATE = 1; static final int MODIFY = 2; static enum Corner { TOPLEFT, BOTTOMLEFT, TOPRIGHT, BOTTOMRIGHT } // Side side; ImageIcon leafIcon = null; ImageIcon javaIcon = null; ImageIcon jarIcon = null; ImageIcon folderIcon = null; ImageIcon classIcon = null; Class<?> jHelpClass = null; Class<?> helpSetClass = null; boolean panSwitch = false; int panX, panY; Cursor openPawCursor = null; Cursor closedPawCursor = null; Cursor drag_icon = null; // "Subnet" is not a separate block type (it is a variant of "Process") String blockNames[] = {"Process", "Initial IP", "Enclosure", "Subnet", "ExtP In", "ExtP Out", "ExtP O/I", "Legend", "File", "Person", "Report"}; String blockTypes[] = {Block.Types.PROCESS_BLOCK, Block.Types.IIP_BLOCK, Block.Types.ENCL_BLOCK, Block.Types.PROCESS_BLOCK, Block.Types.EXTPORT_IN_BLOCK, Block.Types.EXTPORT_OUT_BLOCK, Block.Types.EXTPORT_OUTIN_BLOCK, Block.Types.LEGEND_BLOCK, Block.Types.FILE_BLOCK, Block.Types.PERSON_BLOCK, Block.Types.REPORT_BLOCK,}; //String buttonNames[] = {"Process", "Initial IP", // "Enclosure", "Subnet", "ExtPorts: In", "... Out", // "... Out/In", "Legend", "File", "Person", "Report"}; HashMap<String, String> jarFiles = new HashMap<String, String> (); // JPopupMenu curPopup = null; // currently active popup menu //String scale; boolean tryFindJarFile = true; boolean willBeSubnet = false; JMenuBar menuBar = null; JMenu fileMenu = null; JMenu editMenu = null; JMenu helpMenu = null; JMenuItem gNMenuItem = null; JMenuItem[] gMenu = null; JMenuItem menuItem1 = null; JMenuItem menuItem2 = null; JTextField jtf = new JTextField(); boolean allFiles = false; //int wDiff, hDiff; JComponent jHelpViewer = null; MyFontChooser fontChooser; boolean gFontChanged, fFontChanged; static Color lg = new Color(240, 240, 240); // very light gray static Color slateGray1 = new Color(198, 226, 255); //JDialog popup = null; JDialog popup2 = null; JDialog depDialog = null; static enum Side { LEFT, TOP, RIGHT, BOTTOM } //static boolean READFILE = true; Cursor defaultCursor = null; boolean use_drag_icon = false; JLabel zoom = new JLabel("Zoom"); JCheckBox pan = new JCheckBox("Pan"); JRadioButton[] but = new JRadioButton[11]; Box box21 = null; // constructor DrawFBP(String[] args) { if (args.length == 1) diagramName = args[0]; // frame = new JFrame("DrawFBP"); // int screenRes = Toolkit.getDefaultToolkit().getScreenResolution(); scalingFactor = 1.0d; driver = this; diagDesc = new JLabel(" "); grid = new JCheckBox("Grid"); properties = new HashMap<String, String>(); genLangs = new GenLang[]{ new GenLang("Java", "java", new JavaFileFilter()), new GenLang("C#", "cs", new CsharpFileFilter()), new GenLang("JSON", "json", new JSONFilter()), new GenLang("FBP", "fbp", new FBPFilter()) }; Lang lang0[] = new Lang[]{new Lang("Java", "java") //, new Lang("Groovy", "groovy"), new Lang("Scala", "scala") }; genLangs[0].langs = lang0; Lang lang1[] = new Lang[]{new Lang("C#", "cs")}; genLangs[1].langs = lang1; Lang lang2[] = new Lang[]{ new Lang("JSON", "json")}; genLangs[2].langs = lang2; Lang lang3[] = new Lang[]{new Lang("FBP", "fbp")}; genLangs[3].langs = lang3; // Following array entries are language-independent - they are copied over // to the array of the same name in the Diagram object // The missing array entries are language-dependent, and are set during diagram building or initialization fCPArray[DIAGRAM] = new FileChooserParms("Diagram", "currentDiagramDir", "Specify diagram name in diagram directory", ".drw", driver.new DiagramFilter(), "Diagrams (*.drw)"); fCPArray[IMAGE] = new FileChooserParms("Image", "currentImageDir", "Image: ", ".png", driver.new ImageFilter(), "Image files"); fCPArray[JARFILE] = new FileChooserParms("Jar file", "javaFBPJarFile", "Choose a jar file for JavaFBP", ".jar", driver.new JarFileFilter(), "Jar files"); fCPArray[JHALL] = new FileChooserParms("Java Help file", "jhallJarFile", "Choose a directory for the JavaHelp jar file", ".jar", driver.new JarFileFilter(), "Help files"); createAndShowGUI(); } /** * Create the GUI and show it. For thread safety, this method should be * invoked from the event-dispatching thread. */ private void createAndShowGUI() { // Create and set up the window. Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // label = new JLabel(" "); frame = this; frame.setTitle("DrawFBP Diagram Generator"); SwingUtilities.updateComponentTreeUI(frame); // frame = new JFrame("DrawFBP Diagram Generator"); frame.setUndecorated(false); // can't change size of JFrame title, // though! defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); frame.setCursor(defaultCursor); applyOrientation(frame); int w = (int) dim.getWidth(); int h = (int) dim.getHeight(); //maxX = (int) (w * .8); //maxY = (int) (h * .8); buffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); osg = buffer.createGraphics(); // http://www.oracle.com/technetwork/java/painting-140037.html bs = new BasicStroke(1.5f, BasicStroke.CAP_ROUND, // width 1.5 BasicStroke.JOIN_ROUND); osg.setStroke(bs); osg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // UIDefaults def = UIManager.getLookAndFeelDefaults(); // UIDefaults def = UIManager.getDefaults(); readPropertiesFile(); properties.put("versionNo", "v" + VersionAndTimestamp.getVersion()); properties.put("date", VersionAndTimestamp.getDate()); if (null == (generalFont = properties.get("generalFont"))) generalFont = "Arial"; if (null == (fixedFont = properties.get("fixedFont"))) fixedFont = "Courier"; String dfs = properties.get("defaultFontSize"); if (dfs == null) defaultFontSize = 14.0f; else defaultFontSize = Float.parseFloat(dfs); String dcl = properties.get("defaultCompLang"); //if (dcl.equals("NoFlo")) // transitional! // dcl = "JSON"; if (dcl == null) { defaultCompLang = findGLFromLabel("Java"); propertiesChanged = true; } else { if (dcl.equals("NoFlo")) // transitional! dcl = "JSON"; defaultCompLang = findGLFromLabel(dcl); } Iterator<Entry<String, String>> entries = jarFiles.entrySet().iterator(); String z = ""; String cma = ""; while (entries.hasNext()) { Entry<String, String> thisEntry = entries.next(); z += cma + thisEntry.getKey() + ":" + thisEntry.getValue(); cma = ";"; } properties.put("additionalJarFiles", z); startProperties = new HashMap<String, String>(); for (String s : properties.keySet()) { startProperties.put(s, properties.get(s)); } fontg = new Font(generalFont, Font.PLAIN, (int) defaultFontSize); // read/create time fontf = new Font(fixedFont, Font.PLAIN, (int) defaultFontSize); osg.setFont(fontg); FontMetrics metrics = osg.getFontMetrics(fontg); gFontWidth = metrics.charWidth('n'); // should be the average! gFontHeight = metrics.getAscent() + metrics.getLeading(); jfl = new JTextField(""); jfl.setText("Fixed font: " + fixedFont + "; general font: " + generalFont); jfs = new JTextField(""); jfs.setText("Font Size: " + defaultFontSize); jfv = new JTextField(); jfv.setText("Ver: " + VersionAndTimestamp.getVersion()); jtp = new JTabbedPaneWithCloseIcons(this); jtp.setForeground(Color.BLACK); jtp.setBackground(Color.WHITE); BufferedImage image = loadImage("DrawFBP-logo-small.png"); if (image != null) { favicon = new ImageIcon(image); frame.setIconImage(image); } else { MyOptionPane.showMessageDialog(frame, "Couldn't find file: DrawFBP-logo-small.png", MyOptionPane.ERROR_MESSAGE); // return null; } // frame.repaint(); // frame.update(frame.getGraphics()); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); closeTabAction = new CloseTabAction(); closeAppAction = new CloseAppAction(); escapeAction = new EscapeAction(); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent ev) { closeAppAction.actionPerformed(new ActionEvent(ev, 0, "CLOSE")); } }); jtp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( escapeKS, "CLOSE"); jtp.getActionMap().put("CLOSE", escapeAction); Container cont = frame.getContentPane(); buildUI(cont); frame.add(Box.createRigidArea(new Dimension(0,10))); String t = properties.get("x"); int x = 0, y = 0, w2 = 1200, h2 = 800; if (t != null) x = Integer.parseInt(t); t = properties.get("y"); if (t != null) y = Integer.parseInt(t); Point p = new Point(x, y); frame.setLocation(p); t = properties.get("width"); if (t != null) w2 = Integer.parseInt(t); t = properties.get("height"); if (t != null) h2 = Integer.parseInt(t); Dimension dim2 = new Dimension(w2, h2); frame.setPreferredSize(dim2); frame.repaint(); // Display the window. frame.pack(); frame.setVisible(true); frame.addComponentListener(this); frame.repaint(); //wDiff = frame.getWidth() - curDiag.area.getWidth(); //hDiff = frame.getHeight() - curDiag.area.getHeight(); diagramName = properties.get("currentDiagram"); boolean small = (diagramName) == null ? false : true; if (!small) // try suppressing this... new SplashWindow(frame, 3000, this, small); // display // for 3.0 secs, or until mouse is moved if (diagramName != null) { actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Open " + diagramName)); } frame.repaint(); } private void buildUI(Container container) { buildPropDescTable(); getNewDiag(); MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { int i = jtp.indexAtLocation(e.getX(), e.getY()); if (i == -1) return; ButtonTabComponent b = (ButtonTabComponent) driver.jtp .getTabComponentAt(i); Diagram diag = b.diag; if (diag == null) { getNewDiag(); // diag = new Diagram(driver); // b.diag = diag; } //curDiag = diag; frame.repaint(); } }; jtp.addMouseListener(mouseListener); container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS)); Box box1 = new Box(BoxLayout.Y_AXIS); container.add(box1); Box box4 = new Box(BoxLayout.X_AXIS); box1.add(box4); int sf = (int) Math.round(100.0 * scalingFactor); JSlider zoomControl = new JSlider(JSlider.VERTICAL, 60, 200, sf); zoomControl.setPreferredSize(new Dimension(40, 200)); zoomControl.setMajorTickSpacing(20); // zoomControl.setMinorTickSpacing(10); zoomControl.setPaintTicks(true); zoomControl.setSnapToTicks(true); zoomControl.setPaintLabels(false); zoomControl.setPaintTrack(true); zoomControl.setVisible(true); zoomControl.addChangeListener(this); zoomControl.getInputMap().put(escapeKS, "CLOSE"); zoomControl.getActionMap().put("CLOSE", escapeAction); // zoomControl.setBackground(Color.WHITE); Box box45 = new Box(BoxLayout.Y_AXIS); Box box46 = new Box(BoxLayout.X_AXIS); Box box5 = new Box(BoxLayout.X_AXIS); Box box61 = new Box(BoxLayout.X_AXIS); Box box62 = new Box(BoxLayout.X_AXIS); Box box6 = new Box(BoxLayout.Y_AXIS); box5.add(Box.createRigidArea(new Dimension(10, 0))); box6.add(Box.createRigidArea(new Dimension(0, 10))); scaleLab = new JLabel(); box61.add(scaleLab); box61.add(Box.createRigidArea(new Dimension(5, 0))); box62.add(zoom); box62.add(Box.createRigidArea(new Dimension(5, 0))); box6.add(zoomControl); box6.add(Box.createRigidArea(new Dimension(0, 10))); scaleLab.setForeground(Color.BLUE); String scale = "100%"; scaleLab.setText(scale); box6.add(Box.createRigidArea(new Dimension(0, 10))); box6.add(box61); box6.add(Box.createRigidArea(new Dimension(0, 10))); box6.add(box62); box5.add(box6); box5.add(Box.createRigidArea(new Dimension(10, 0))); //grid.setAlignmentX(JComponent.LEFT_ALIGNMENT); grid.setFont(fontg); grid.setSelected(true); // box.add(grid); grid.setActionCommand("Toggle Click to Grid"); grid.addActionListener(this); grid.setBackground(slateGray1); grid.setBorderPaintedFlat(false); box6.add(Box.createRigidArea(new Dimension(0, 10))); box45.add(box5); box45.add(Box.createRigidArea(new Dimension(0, 10))); box46.add(grid); box46.add(Box.createRigidArea(new Dimension(0, 10))); box45.add(box46); // scaleLab.setFont(fontg); box4.add(box45); Point p = jtp.getLocation(); jtp.setLocation(p.x + 100, p.y); box4.add(jtp); box4.add(Box.createRigidArea(new Dimension(50, 0))); // jtp.setBackground(Color.WHITE); // Align the left edges of the components. curDiag.area.setAlignmentX(Component.LEFT_ALIGNMENT); diagDesc.setAlignmentX(Component.CENTER_ALIGNMENT); // label.setLabelFor(area); box1.add(diagDesc); Font ft = fontg.deriveFont(Font.BOLD); diagDesc.setFont(ft); diagDesc.setPreferredSize(new Dimension(0, gFontHeight * 2)); diagDesc.setForeground(Color.BLUE); box1.add(Box.createRigidArea(new Dimension(0, 4))); Box box2 = new Box(BoxLayout.X_AXIS); //JScrollPane jsp = new JScrollPane(); //box2.add(jsp); box2.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY)); box1.add(box2); //box2.add(Box.createHorizontalGlue()); box2.add(pan); //.addbox2(Box.createHorizontalGlue()); box2.add(Box.createRigidArea(new Dimension(10, 0))); //box2.add(Box.createHorizontalGlue()); pan.setSelected(false); pan.setFont(fontg); pan.setActionCommand("Toggle Pan Switch"); pan.addActionListener(this); pan.setBackground(slateGray1); pan.setBorderPaintedFlat(false); // pan.setBorder(null); // pan.setPreferredSize(new Dimension(50, 20)); ButtonGroup butGroup = new ButtonGroup(); box21 = new Box(BoxLayout.X_AXIS); box2.add(box21); for (int j = 0; j < but.length; j++) { but[j] = new JRadioButton(); but[j].addActionListener(this); butGroup.add(but[j]); box21.add(but[j]); //jsp.add(but[j]); //but[j].setFont(fontg); but[j].setText(blockNames[j]); but[j].setFocusable(true); } but[but.length - 1].setAlignmentX(Component.RIGHT_ALIGNMENT); //box21.add(Box.createRigidArea(new Dimension(10,0))); //box21.add(Box.createHorizontalStrut(10)); adjustFonts(); but[0].setSelected(true); // "Process" box2.add(Box.createRigidArea(new Dimension(10,0))); //box2.add(Box.createHorizontalGlue()); for (int j = 0; j < but.length; j++) { but[j].getInputMap().put(escapeKS, "CLOSE"); but[j].getActionMap().put("CLOSE", escapeAction); } BufferedImage image = loadImage("DrawFBP-logo-small.jpg"); frame.setIconImage(image); leafIcon = new ImageIcon(image); image = loadImage("javaIcon.jpg"); javaIcon = new ImageIcon(image); image = loadImage("jarIcon.jpg"); jarIcon = new ImageIcon(image); image = loadImage("folderIcon.jpg"); folderIcon = new ImageIcon(image); image = loadImage("classIcon.jpg"); classIcon = new ImageIcon(image); Toolkit tk = Toolkit.getDefaultToolkit(); image = null; openPawCursor = null; image = loadImage("open_paw.gif"); openPawCursor = tk.createCustomCursor(image, new Point(15, 15), "Paw"); closedPawCursor = null; image = loadImage("closed_paw.gif"); closedPawCursor = tk .createCustomCursor(image, new Point(15, 15), "Paw"); image = loadImage("drag_icon.gif"); drag_icon = tk.createCustomCursor(image, new Point(1, 1), "Drag"); } BufferedImage loadImage(String s) { InputStream is = this.getClass().getClassLoader() .getResourceAsStream(s); BufferedImage image = null; if (is == null) { MyOptionPane.showMessageDialog(frame, "Missing icon: " + s, MyOptionPane.ERROR_MESSAGE); } else { try { image = ImageIO.read(is); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return image; } public void createMenuBar() throws IOException { //JMenu editMenu; // Create the menu bar. menuBar = new JMenuBar(); // menuBar.add(Box.createRigidArea(new Dimension(20, 0))); // menuBar.setColor(new Color(200, 255, 255)); // Build the first menu. //fileMenu = new JMenu(" File "); fileMenu.setMnemonic(KeyEvent.VK_F); // fileMenu.setSelected(true); fileMenu.setBorderPainted(true); //fileMenu.setFont(fontg); menuBar.add(fileMenu); // a group of JMenuItems JMenuItem menuItem = new JMenuItem("Open Diagram"); // menu.setMnemonic(KeyEvent.VK_D); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK)); fileMenu.add(menuItem); menuItem.addActionListener(this); menuItem = new JMenuItem("Save"); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.ALT_MASK)); fileMenu.add(menuItem); menuItem.addActionListener(this); menuItem = new JMenuItem("Save as..."); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK)); fileMenu.add(menuItem); menuItem.addActionListener(this); menuItem = new JMenuItem("New Diagram"); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.ALT_MASK)); fileMenu.add(menuItem); menuItem.addActionListener(this); fileMenu.addSeparator(); JMenu gnMenu = new JMenu("Select Diagram Language..."); fileMenu.add(gnMenu); int j = genLangs.length; gMenu = new JMenuItem[j]; int k = 0; for (int i = 0; i < j; i++) { if (!(genLangs[i].label.equals("FBP"))){ gMenu[k] = new JMenuItem(genLangs[i].label); gnMenu.add(gMenu[k]); gMenu[k].addActionListener(this); k++; } } // menuItem = new JMenuItem("Clear Language Association"); // fileMenu.add(menuItem); // menuItem.addActionListener(this); fileMenu.addSeparator(); menuItem = new JMenuItem("Export Image"); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, ActionEvent.ALT_MASK)); fileMenu.add(menuItem); menuItem.addActionListener(this); menuItem = new JMenuItem("Show Image"); fileMenu.add(menuItem); menuItem.addActionListener(this); fileMenu.addSeparator(); String s = "Generate "; if (curDiag != null) s += curDiag.diagLang.label + " "; s += "Network"; gNMenuItem = new JMenuItem(s); fileMenu.add(gNMenuItem); gNMenuItem.addActionListener(this); menuItem = new JMenuItem("Display Generated Code"); fileMenu.add(menuItem); menuItem.addActionListener(this); fileMenu.addSeparator(); //JMenuItem runMenu = new JMenuItem("Run Command"); //runMenu.setMnemonic(KeyEvent.VK_R); //runMenu.setBorderPainted(true); //fileMenu.add(runMenu); //runMenu.addActionListener(this); //fileMenu.addSeparator(); menuItem = new JMenuItem("Generate .fbp code"); fileMenu.add(menuItem); menuItem.addActionListener(this); fileMenu.addSeparator(); //if (curDiag != null // &&curDiag.diagLang != null // && curDiag.diagLang.label.equals("Java")){ menuItem1 = new JMenuItem("Locate JavaFBP Jar File"); if (defaultCompLang == null || !( defaultCompLang.label.equals("Java"))) menuItem1.setEnabled(false); else menuItem1.setEnabled(true); fileMenu.add(menuItem1); menuItem1.addActionListener(this); menuItem2 = new JMenuItem("Add Additional Component Jar File"); if (defaultCompLang == null || !( defaultCompLang.label.equals("Java"))) menuItem2.setEnabled(false); else menuItem2.setEnabled(true); fileMenu.add(menuItem2); menuItem2.addActionListener(this); fileMenu.addSeparator(); menuItem = new JMenuItem("Locate DrawFBP Help File"); fileMenu.add(menuItem); menuItem.addActionListener(this); //} fileMenu.addSeparator(); menuItem = new JMenuItem("Change Fonts"); fileMenu.add(menuItem); menuItem.addActionListener(this); menuItem = new JMenuItem("Change Font Size"); fileMenu.add(menuItem); menuItem.addActionListener(this); fileMenu.addSeparator(); menuItem = new JMenuItem("Print"); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.ALT_MASK)); fileMenu.add(menuItem); menuItem.addActionListener(this); fileMenu.addSeparator(); menuItem = new JMenuItem("Display Properties"); fileMenu.add(menuItem); menuItem.addActionListener(this); fileMenu.addSeparator(); menuItem = new JMenuItem("Close Diagram"); fileMenu.add(menuItem); menuItem.addActionListener(this); //editMenu = new JMenu(" Edit "); editMenu.setMnemonic(KeyEvent.VK_E); //editMenu.setFont(fontg); menuBar.add(editMenu); editMenu.setBorderPainted(true); menuItem = new JMenuItem("Edit Diagram Description"); editMenu.add(menuItem); menuItem.addActionListener(this); menuItem = new JMenuItem("New Block"); editMenu.add(menuItem); menuItem.addActionListener(this); menuItem = new JMenuItem("Block-related Actions"); editMenu.add(menuItem); menuItem.addActionListener(this); menuItem = new JMenuItem("Arrow-related Actions"); editMenu.add(menuItem); menuItem.addActionListener(this); //JMenu helpMenu = new JMenu(" Help "); helpMenu.setMnemonic(KeyEvent.VK_H); //helpMenu.setFont(fontg); helpMenu.setBorderPainted(true); // helpMenu.setColor(new Color(121, 201, 201)); menuBar.add(helpMenu); Box box0 = new Box(BoxLayout.X_AXIS); //JPanel jp1 = new JPanel(); Dimension dim = jtf.getPreferredSize(); jtf.setPreferredSize(new Dimension(gFontWidth * 20, dim.height)); box0.add(Box.createRigidArea(new Dimension(20,0))); box0.add(jtf); // languages box0.add(Box.createRigidArea(new Dimension(10,0))); box0.add(jfl); // font list box0.add(Box.createRigidArea(new Dimension(10,0))); box0.add(jfs); // font size box0.add(Box.createRigidArea(new Dimension(10,0))); box0.add(jfv); menuBar.add(box0); jtf.setText(defaultCompLang.showLangs()); jtf.setFont(fontg); jtf.setEditable(false); //jtf.setBackground(slateGray1); //jfl.setBackground(slateGray1); jfl.setFont(fontg); jfl.setEditable(false); jfs.setFont(fontg); jfs.setEditable(false); JMenuItem menu_help = new JMenuItem("Launch Help"); helpMenu.add(menu_help); menu_help.addActionListener(this); menuItem = new JMenuItem("About"); helpMenu.add(menuItem); menuItem.addActionListener(this); menuBar.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( escapeKS, "CLOSE"); menuBar.getActionMap().put("CLOSE", escapeAction); menuBar.setVisible(true); repaint(); return; } void getNewDiag() { Diagram diag = new Diagram(this); SelectionArea sa = getNewArea(); diag.area = sa; int i = jtp.getTabCount(); jtp.add(sa, new JLabel()); ButtonTabComponent b = new ButtonTabComponent(jtp, this); jtp.setTabComponentAt(i, b); jtp.setSelectedIndex(i); b.diag = diag; diag.tabNum = i; curDiag = diag; return; } @SuppressWarnings("rawtypes") public void actionPerformed(ActionEvent e) { if (e.getSource() == jfl) { changeFonts(); return; } if (e.getSource() == jfs) { changeFontSize(); return; } String s = e.getActionCommand(); if (s.equals("Open Diagram")) { openAction(null); return; } if (s.length() > 5 && s.substring(0, 5).equals("Open ")) { s = s.substring(5); // drop Open and blank openAction(s); return; } boolean SAVE_AS = true; if (s.equals("Save")) { saveAction(!SAVE_AS); return; } if (s.equals("Save as...")) { saveAction(SAVE_AS); return; } if (s.equals("New Diagram")) { int i = jtp.getTabCount(); if (i > 1 || curDiag.diagFile != null || curDiag.changed) getNewDiag(); jtp.setSelectedIndex(curDiag.tabNum); frame.repaint(); return; } // if (curDiag.compLang == null) { for (int j = 0; j < gMenu.length; j++) { if (e.getSource() == gMenu[j]) { GenLang gl = genLangs[j]; defaultCompLang = gl; properties.put("defaultCompLang", defaultCompLang.label); propertiesChanged = true; if (curDiag != null && curDiag.diagLang != defaultCompLang) { curDiag.diagLang = defaultCompLang; curDiag.changed = true; } changeLanguage(gl); MyOptionPane.showMessageDialog( frame, "Language group changed to " + defaultCompLang.showLangs()); frame.repaint(); return; } } // } if (s.equals("Generate .fbp code")) { if (curDiag == null || curDiag.blocks.isEmpty()) { MyOptionPane.showMessageDialog(frame, "No components specified", MyOptionPane.ERROR_MESSAGE); return; } if (curDiag.title == null || curDiag.title.equals("(untitled)")) { MyOptionPane.showMessageDialog(frame, "Untitled diagram - please do Save first", MyOptionPane.ERROR_MESSAGE); return; } CodeManager mc = new CodeManager(curDiag); if (!mc.genFbpCode()) MyOptionPane.showMessageDialog(frame, "Error in code generation", MyOptionPane.ERROR_MESSAGE); return; } if (s.startsWith("Generate ")) { if (curDiag == null || curDiag.blocks.isEmpty()) { MyOptionPane.showMessageDialog(frame, "No components specified", MyOptionPane.ERROR_MESSAGE); return; } if (curDiag.title == null || curDiag.title.equals("(untitled)")) { MyOptionPane.showMessageDialog(frame, "Untitled diagram - please do Save first", MyOptionPane.ERROR_MESSAGE); return; } CodeManager mc = new CodeManager(curDiag); mc.genCode(); return; } if (s.equals("Display Generated Code")) { File cFile = null; GenLang gl = curDiag.diagLang; // String ss = properties.get("currentImageDir"); String ss = properties.get(gl.netDirProp); String name = curDiag.diagFile.getName(); if (ss == null) ss = System.getProperty("user.home"); File file = new File(ss); MyFileChooser fc = new MyFileChooser(file, curDiag.fCPArr[GENCODE]); int i = name.indexOf(".drw"); ss += File.separator + name.substring(0, i) + curDiag.fCPArr[GENCODE].fileExt; fc.setSuggestedName(ss); int returnVal = fc.showOpenDialog(true); // force saveAs cFile = null; if (returnVal == MyFileChooser.APPROVE_OPTION) { cFile = new File(getSelFile(fc)); } // } if (cFile == null) return; if (!(cFile.exists())) return; CodeManager mc = new CodeManager(curDiag); mc.display(cFile, gl); return; } /* if (s.equals("Run Code")) { File cFile = null; GenLang gl = curDiag.diagLang; // String ss = properties.get("currentImageDir"); String ss = properties.get(gl.netDirProp); File genDir = null; if (ss == null) genDir = new File(System.getProperty("user.home")); else genDir = new File(ss); MyFileChooser fc = new MyFileChooser(genDir, curDiag.fCPArr[GENCODE], frame); int returnVal = fc.showOpenDialog(); cFile = null; if (returnVal == MyFileChooser.APPROVE_OPTION) { cFile = new File(getSelFile(fc)); } // } if (cFile == null) return; if (!(cFile.exists())) return; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); int result = compiler.run(null, null, null, cFile.getAbsolutePath()); return; } */ // Run Command temporarily disabled if (s.equals("Run Command")) { String command = ""; readPropertiesFile(); if (null == (command = properties.get("runCommand"))) command = "echo Enter command"; String ans = (String) MyOptionPane.showInputDialog(driver.frame, "Enter or change text", "Command with no diagram name", MyOptionPane.PLAIN_MESSAGE, null, null, command); if (ans != null && ans.length() > 0) { command = ans; properties.put("runCommand", command); propertiesChanged = true; } Process p = null; String realCommand = ""; if ((System.getProperty("os.name")).startsWith("Windows")) realCommand += "cmd /c "; realCommand += command; String jSONNetworkDir = null; if (curDiag.title == null) MyOptionPane.showMessageDialog(frame, "No diagram selected: executing command with no diagram JSON", MyOptionPane.ERROR_MESSAGE); else { if (null == (jSONNetworkDir = properties .get("currentJSONNetworkDir"))) { MyOptionPane.showMessageDialog(frame, "Diagram selected but JSON directory missing: generate JSON from diagram \n" + "will prompt for JSON directory", MyOptionPane.ERROR_MESSAGE); return; } String fileName = jSONNetworkDir + File.separator + curDiag.title + ".json"; File file = new File(fileName); if (!file.isFile()){ MyOptionPane.showMessageDialog(frame, "JSON file for diagram does not exist: generate JSON from diagram", MyOptionPane.ERROR_MESSAGE); return; } realCommand += " " + fileName; } ans = (String) MyOptionPane.showInputDialog(driver.frame, "Enter or change text", "Actual command", MyOptionPane.PLAIN_MESSAGE, null, null, realCommand); if (ans != null && ans.length() > 0) { realCommand = ans; //properties.put("runCommand", realCommand); //propertiesChanged = true; } try { p = Runtime.getRuntime().exec(realCommand); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // final JEditorPane pane = new JEditorPane(); final JFrame jframe = new JFrame("Run Output"); final JEditorPane pane = new JEditorPane("text/plain", " "); pane.setEditable(false); JScrollPane scrollPane = new JScrollPane(pane); jframe.add(scrollPane); jframe.setVisible(true); pane.setVisible(true); scrollPane.setVisible(true); pane.setFont(fontf); jframe.setSize(600, 400); jframe.setLocation(100, 50); jframe.addWindowListener(new WindowAdapter() { @Override public void windowClosing(final WindowEvent ev) { jframe.dispose(); } }); MyRunnable r = new MyRunnable(pane) { public void run() { BufferedReader input = new BufferedReader( new InputStreamReader(proc.getInputStream())); String line = null; try { while ((line = input.readLine()) != null) { try { Document doc = pane.getDocument(); doc.insertString(doc.getLength(), line, null); } catch (BadLocationException exc) { exc.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } } }; r.proc = p; new Thread(r).start(); try { r.proc.waitFor(); } catch (InterruptedException ev) { // TODO Auto-generated catch block ev.printStackTrace(); } } if (s.equals("Clear Language Association")) { curDiag.diagLang = null; curDiag.changed = true; jtf.setText(""); // curDiag.changeCompLang(); } // } if (s.equals("Locate JavaFBP Jar File")) { locateJavaFBPJarFile(); return; } if (s.equals("Add Additional Component Jar File")) { addAdditionalJarFile(); return; } if (s.equals("Locate DrawFBP Help File")) { locateJhallJarFile(); return; } if (s.equals("Change Fonts")) { changeFonts(); } if (s.equals("Change Font Size")) { changeFontSize(); } if (s.equals("Print")) { int x1, w1, y1, h1; x1 = curDiag.area.getX(); y1 = curDiag.area.getY(); w1 = curDiag.area.getWidth(); h1 = curDiag.area.getHeight(); Rectangle rect = new Rectangle(x1, y1, w1, h1); PrintableDocument pd = new PrintableDocument( frame.getContentPane(), this); // PrintableDocument.printComponent(frame.getContentPane()); pd.setRectangle(rect); // doesn't seem to make a difference! pd.print(); return; } if (s.equals("Display Properties")) { displayProperties(); } if (s.equals("Toggle Click to Grid")) { curDiag.clickToGrid = !curDiag.clickToGrid; grid.setSelected(curDiag.clickToGrid); return; } if (s.equals("Toggle Pan Switch")) { panSwitch = !panSwitch; //if (panSwitch) // frame.setCursor(openPawCursor); //else // frame.setCursor(defaultCursor); return; } if (s.equals("Export Image")) { if (curDiag == null || curDiag.title == null || curDiag.blocks.isEmpty()) { MyOptionPane.showMessageDialog(null, "Unable to export image for empty or unsaved diagram - please do save first", MyOptionPane.ERROR_MESSAGE); return; } File file = null; //curDiag.imageFile = null; // crop int x1, w1, y1, h1; x1 = Math.max(1, curDiag.minX); w1 = curDiag.maxX - x1; y1 = Math.max(1, curDiag.minY); h1 = curDiag.maxY - y1; int w = curDiag.area.getWidth(); int h = curDiag.area.getHeight(); w1 = Math.min(w1, w - x1); h1 = Math.min(h1, h - y1); BufferedImage buffer2 = buffer.getSubimage(x1, y1, w1, h1); //int w2 = buffer2.getWidth(); //int h2 = buffer2.getHeight(); BufferedImage combined = new BufferedImage(w1, h1 + 100, BufferedImage.TYPE_INT_ARGB); Graphics g = combined.getGraphics(); //Graphics g = buffer2.getGraphics(); g.setColor(Color.WHITE); //g.fillRect(0, 0, w1, h1 + 100); g.drawImage(buffer2, 0, 0, null); //g.setColor(Color.RED); g.fillRect(0, h1, w1, 100); if (curDiag.desc != null) { Color col = g.getColor(); g.setColor(Color.BLUE); Font f = fontg.deriveFont(Font.ITALIC, 18.0f); g.setFont(f); int x = combined.getWidth() / 2; //int x = buffer2.getWidth() / 2; FontMetrics metrics = g.getFontMetrics(f); String t = curDiag.desc; byte[] str = t.getBytes(); int width = metrics.bytesWidth(str, 0, t.length()); g.drawString(t, x - width / 2, buffer2.getHeight() + 40); g.setColor(col); } int i = curDiag.fCPArr[IMAGE].prompt.indexOf(":"); String fn; if (curDiag.diagFile == null) fn = "(null)"; else fn = curDiag.diagFile.getName(); curDiag.fCPArr[IMAGE].prompt = curDiag.fCPArr[IMAGE].prompt .substring(0, i) + ": " + fn; file = curDiag.genSave(null, fCPArray[IMAGE], combined); //file = curDiag.genSave(null, fCPArray[IMAGE], buffer2); if (file == null) { MyOptionPane.showMessageDialog(frame, "File not saved"); // curDiag.imageFile = null; g.dispose(); return; } // ImageIcon image = new ImageIcon(combined); //curDiag.imageFile = file; Date date = new Date(); file.setLastModified(date.getTime()); return; } if (s.equals("Show Image")) { File fFile = null; //if (fFile == null || !fFile.exists()) { String ss = properties.get("currentImageDir"); if (ss == null) currentImageDir = new File(System.getProperty("user.home")); else currentImageDir = new File(ss); MyFileChooser fc = new MyFileChooser(currentImageDir, curDiag.fCPArr[IMAGE]); int i = curDiag.diagFile.getName().indexOf(".drw"); ss += File.separator + curDiag.diagFile.getName().substring(0, i) + curDiag.fCPArr[IMAGE].fileExt; fc.setSuggestedName(ss); int returnVal = fc.showOpenDialog(true); // set to saveAs // fFile = null; if (returnVal == MyFileChooser.APPROVE_OPTION) { fFile = new File(getSelFile(fc)); } // } if (fFile == null) return; if (!(fFile.exists())) return; //} BufferedImage buffer2 = new BufferedImage(1200, 2000, BufferedImage.TYPE_INT_RGB); try { buffer2 = ImageIO.read(fFile); } catch (IOException e2) { MyOptionPane.showMessageDialog(frame, "Could not get image", MyOptionPane.ERROR_MESSAGE); } ImageIcon image = new ImageIcon(buffer2); currentImageDir = new File(fFile.getParent()); properties.put("currentImageDir", fFile.getParent()); propertiesChanged = true; //curDiag.imageFile = fFile; JDialog popup = new JDialog(); popup.setTitle(fFile.getName()); JLabel jLabel = new JLabel(image); jLabel.addComponentListener(this); JScrollPane jsp = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); jsp.getViewport().add(jLabel); Dimension dim = new Dimension(image.getIconWidth(), image.getIconHeight()); jsp.getViewport().setPreferredSize(dim); jsp.getViewport().setBackground(Color.WHITE); jLabel.setBackground(Color.WHITE); popup.add(jsp, BorderLayout.CENTER); popup.setLocation(new Point(200, 200)); popup.setBackground(Color.WHITE); //popup.addComponentListener(this); //popup.setPreferredSize(dim); popup.pack(); popup.setVisible(true); popup.setAlwaysOnTop(true); popup.repaint(); frame.repaint(); return; } if (s.equals("Close Diagram")) { closeTab(); return; } if (s.equals("Launch Help")) { // The following is based on // https://supportweb.cs.bham.ac.uk/documentation/tutorials/ // docsystem/build/tutorials/javahelp/javahelp.html // plus reflection if (jHelpViewer == null) { if (jhallJarFile == null) { jhallJarFile = properties.get("jhallJarFile"); boolean res = true; if (jhallJarFile == null) { int response = MyOptionPane .showConfirmDialog( frame, //"Locate it?", "Specify the location of the JavaHelp jar file -\n" + "do a search on Maven Central for 'javahelp'\n" + "Artifact ID: javahelp", "Locate it?", MyOptionPane.OK_CANCEL_OPTION); if (response == MyOptionPane.OK_OPTION) res = locateJhallJarFile(); else { MyOptionPane.showMessageDialog(frame, "No DrawFBP Help jar file located", MyOptionPane.ERROR_MESSAGE); res = false; } } if (!res) return; } jHelpClass = null; helpSetClass = null; URLClassLoader cl = null; File jFile = new File(jhallJarFile); if (!(jFile.exists())) { MyOptionPane .showMessageDialog( frame, "DrawFBP Help jar file shown in properties does not exist\n" + "Use File/Locate DrawFBP Help File, and try Help again", MyOptionPane.ERROR_MESSAGE); return; } try { URL[] urls = new URL[]{jFile.toURI().toURL()}; // Create a new class loader with the directory cl = new URLClassLoader(urls, this.getClass() .getClassLoader()); // Find the HelpSet file and create the HelpSet object helpSetClass = cl.loadClass("javax.help.HelpSet"); } catch (MalformedURLException e2) { } catch (ClassNotFoundException e2) { } catch (NoClassDefFoundError e2) { } if (helpSetClass == null) { MyOptionPane.showMessageDialog(frame, "HelpSet class not found in jar file or invalid", MyOptionPane.ERROR_MESSAGE); return; } URL url2 = null; jHelpViewer = null; try { Method m = helpSetClass.getMethod("findHelpSet", ClassLoader.class, String.class); url2 = (URL) m.invoke(null, cl, "helpSet.hs"); Constructor conhs = helpSetClass.getConstructor( ClassLoader.class, URL.class); Object hs = conhs.newInstance(cl, url2); jHelpClass = cl.loadClass("javax.help.JHelp"); if (jHelpClass == null) { MyOptionPane.showMessageDialog(frame, "JHelp class not found in jar file", MyOptionPane.ERROR_MESSAGE); return; } Constructor conjh = jHelpClass.getConstructor(helpSetClass); jHelpViewer = (JComponent) conjh.newInstance(hs); } catch (Exception e2) { MyOptionPane.showMessageDialog(frame, "HelpSet could not be processed: " + e2, MyOptionPane.ERROR_MESSAGE); return; } } // Create a new frame. popup2 = new JDialog(frame); popup2.setTitle("Help DrawFBP"); popup2.setIconImage(favicon.getImage()); applyOrientation(popup2); popup2.setFocusable(true); popup2.requestFocusInWindow(); popup2.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent ev) { if (ev.getKeyCode() == KeyEvent.VK_ESCAPE) { // frame2.setVisible(false); popup2.dispose(); } } }); jHelpViewer.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( escapeKS, "CLOSE"); jHelpViewer.getActionMap().put("CLOSE", escapeAction); // frame2.setPreferredSize(frame.getPreferredSize()); // Add the created helpViewer to it. popup2.getContentPane().add(jHelpViewer); // Set a default close operation. popup2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // Make the frame visible. popup2.setVisible(true); popup2.pack(); Dimension dim = frame.getSize(); Point p = frame.getLocation(); int x_off = 100; int y_off = 100; popup2.setPreferredSize(new Dimension(dim.width - x_off * 2, dim.height - y_off)); popup2.pack(); popup2.setLocation(p.x + x_off, p.y + y_off); return; } if (s.equals("About")) { JTextArea ta = new JTextArea(); Font f = fontf; ta.setColumns(80); ta.setRows(7); ta.setEditable(false); ta.setBorder(BorderFactory.createLineBorder(Color.BLACK)); ta.setLineWrap(true); String v = VersionAndTimestamp.getVersion(); String dt = VersionAndTimestamp.getDate(); int i = v.length(); String sp1 = " ".substring(0, 7 - i); i = dt.length(); String sp2 = " ".substring(0, 14 - i); ta.setText("****************************************************\n" + "* *\n" + "* DrawFBP v" + v + " "+ sp1 +" *\n" + "* *\n" + "* Authors: J.Paul Rodker Morrison, *\n" + "* Bob Corrick *\n" + "* *\n" + "* Copyright 2009, ..., 2017 *\n" + "* *\n" + "* FBP web site: www.jpaulmorrison.com/fbp *\n" + "* *\n" + "* (" + dt + ") "+ sp2 +" *\n" + "* *\n" + "****************************************************\n"); ta.setFont(f); final JDialog popup = new JDialog(frame); popup.add(ta, BorderLayout.CENTER); Point p = frame.getLocation(); //popup.setPreferredSize(new Dimension(60,20)); popup.pack(); popup.setLocation(p.x + 200, p.y + 100); popup.setVisible(true); popup.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent ev) { popup.dispose(); } }); popup.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent ev) { if (ev.getKeyCode() == KeyEvent.VK_ESCAPE) { popup.dispose(); } } }); popup.requestFocusInWindow(); popup.repaint(); frame.repaint(); return; } if (s.equals("Edit Diagram Description")) { // Title of diagram // as a whole String ans = (String) MyOptionPane.showInputDialog(frame, "Enter or change text", "Modify diagram description", MyOptionPane.PLAIN_MESSAGE, null, null, curDiag.desc); if (ans != null/* && ans.length() > 0*/) { curDiag.desc = ans; curDiag.desc = curDiag.desc.replace('\n', ' '); curDiag.desc = curDiag.desc.trim(); curDiag.changed = true; if (curDiag.parent != null) curDiag.parent.description = ans; } frame.repaint(); return; } if (s.equals("New Block")) { // if (newItemMenu == null) { // newItemMenu = buildNewItemMenu(driver); // } // newItemMenu.setVisible(true); curDiag.xa = 100 + (new Random()) .nextInt(curDiag.area.getWidth() - 200); curDiag.ya = 100 + (new Random()) .nextInt(curDiag.area.getHeight() - 200); if (null != createBlock(blockType)) curDiag.changed = true; frame.repaint(); return; } if (s.equals("Block-related Actions")) { Block b = selBlock; if (b == null) { MyOptionPane.showMessageDialog(frame, "Block not selected", MyOptionPane.ERROR_MESSAGE); return; } curDiag = b.diag; b.buildBlockPopupMenu(); use_drag_icon = false; curDiag.jpm.show(frame, curDiag.xa + 100, curDiag.ya + 100); frame.repaint(); return; } if (s.equals("Arrow-related Actions")) { Arrow a = selArrow; if (a == null) { MyOptionPane.showMessageDialog(frame, "Arrow not selected", MyOptionPane.ERROR_MESSAGE); return; } a.buildArrowPopupMenu(); curDiag = a.diag; curDiag.jpm.show(frame, a.toX + 100, a.toY + 100); frame.repaint(); return; } setBlkType(s); frame.repaint(); } void setBlkType(String s) { if (s.equals("none")) { blockType = ""; } else if (s.equals("Subnet")) { blockType = Block.Types.PROCESS_BLOCK; willBeSubnet = true; } else { willBeSubnet = false; if (s.equals("Process")) { blockType = Block.Types.PROCESS_BLOCK; } else if (s.equals("File")) { blockType = Block.Types.FILE_BLOCK; } else if (s.equals("Report")) { blockType = Block.Types.REPORT_BLOCK; } else if (s.equals("ExtPorts: In")) { blockType = Block.Types.EXTPORT_IN_BLOCK; // In } else if (s.equals("... Out")) { blockType = Block.Types.EXTPORT_OUT_BLOCK;// Out } else if (s.equals("... Out/In")) { blockType = Block.Types.EXTPORT_OUTIN_BLOCK; // Out/In } else if (s.equals("Initial IP")) { blockType = Block.Types.IIP_BLOCK; } else if (s.equals("Legend")) { blockType = Block.Types.LEGEND_BLOCK; } else if (s.equals("Person")) { blockType = Block.Types.PERSON_BLOCK; } else if (s.equals("Enclosure")) { blockType = Block.Types.ENCL_BLOCK; } } } void changeLanguage(GenLang gl) { curDiag.diagLang = gl; defaultCompLang = gl; jtf.setText("Diagram Language: " + gl.showLangs()); jtf.repaint(); if (!defaultCompLang.label.equals("Java")) { menuItem1.setEnabled(false); menuItem2.setEnabled(false); } else { menuItem1.setEnabled(true); menuItem2.setEnabled(true); } fileMenu.remove(gNMenuItem); String u = "Generate "; if (curDiag != null) u += curDiag.diagLang.label + " "; u += "Network"; gNMenuItem = new JMenuItem(u); gNMenuItem.addActionListener(this); fileMenu.add(gNMenuItem, 10); curDiag.filterOptions[0] = gl.showLangs(); curDiag.fCPArr[DrawFBP.PROCESS] = driver.new FileChooserParms( "Process", gl.srcDirProp, "Select " + gl.showLangs() + " component from directory", gl.suggExtn, gl.filter, "Components: " + gl.showLangs() + " " + gl.showSuffixes()); curDiag.fCPArr[DrawFBP.GENCODE] = driver.new FileChooserParms( "Generated code", gl.netDirProp, "Specify file name for generated code", "." + gl.suggExtn, gl.filter, gl.showLangs()); frame.repaint(); } Block createBlock(String blkType) { Block block = null; boolean oneLine = false; if (blkType == Block.Types.PROCESS_BLOCK) { block = new ProcessBlock(curDiag); block.isSubnet = willBeSubnet; } else if (blkType == Block.Types.EXTPORT_IN_BLOCK || blkType == Block.Types.EXTPORT_OUT_BLOCK || blkType == Block.Types.EXTPORT_OUTIN_BLOCK){ oneLine = true; block = new ExtPortBlock(curDiag); } else if (blkType == Block.Types.FILE_BLOCK) block = new FileBlock(curDiag); else if (blkType == Block.Types.IIP_BLOCK) { oneLine = true; block = new IIPBlock(curDiag); } else if (blkType == Block.Types.LEGEND_BLOCK) block = new LegendBlock(curDiag); else if (blkType == Block.Types.ENCL_BLOCK) { oneLine = true; block = new Enclosure(curDiag); Point pt = curDiag.area.getLocation(); int y = Math.max(curDiag.ya - block.height / 2, pt.y + 6); block.cy = ((curDiag.ya + block.height / 2) + y) / 2; } else if (blkType == Block.Types.PERSON_BLOCK) block = new PersonBlock(curDiag); else if (blkType == Block.Types.REPORT_BLOCK) block = new ReportBlock(curDiag); else return null; block.type = blkType; block.cx = curDiag.xa; block.cy = curDiag.ya; if (block.cx == 0 || block.cy == 0) return null; // fudge! //if (enterDesc) { if (oneLine) { if (blkType != Block.Types.ENCL_BLOCK) { String d = "Enter single line value"; String ans = (String) MyOptionPane.showInputDialog(driver.frame, "Enter text", d, MyOptionPane.PLAIN_MESSAGE, null, null, block.description); if (ans == null) return null; else block.description = ans; } } else if (!block.editDescription(REG_CREATE)) return null; if (blkType == Block.Types.IIP_BLOCK) { IIPBlock ib = (IIPBlock) block; block.description = ib.checkNestedChars(block.description); } //} block.calcEdges(); //curDiag.maxBlockNo++; //block.id = curDiag.maxBlockNo; curDiag.blocks.put(new Integer(block.id), block); //curDiag.changed = true; selBlock = block; // selArrowP = null; return block; } void buildPropDescTable() { propertyDescriptions = new LinkedHashMap<String, String>(); propertyDescriptions.put("Version #", "versionNo"); propertyDescriptions.put("Date", "date"); propertyDescriptions.put("Current C# source code directory", "currentCsharpSourceDir"); propertyDescriptions.put("Current C# network code directory", "currentCsharpNetworkDir"); propertyDescriptions.put("Current component class directory", "currentClassDir"); propertyDescriptions.put("Current diagram directory", "currentDiagramDir"); propertyDescriptions.put("Current diagram", "currentDiagram"); propertyDescriptions.put("Current image directory", "currentImageDir"); propertyDescriptions.put("Current Java source code directory", "currentSourceDir"); propertyDescriptions.put("Current Java source code directory", "currentJavaSourceDir"); propertyDescriptions.put("Current Java network code directory", "currentJavaNetworkDir"); propertyDescriptions.put("Current NoFlo source code directory", "currentNoFloSourceDir"); propertyDescriptions.put("Current NoFlo network code directory", "currentNoFloNetworkDir"); propertyDescriptions.put("Current .fbp notation directory", "currentFBPNetworkDir"); propertyDescriptions.put("Current package name", "currentPackageName"); propertyDescriptions.put("Font for code", "fixedFont"); propertyDescriptions.put("Font for text", "generalFont"); propertyDescriptions.put("Default font size", "defaultFontSize"); propertyDescriptions.put("Default component language", "defaultCompLang"); propertyDescriptions.put("JavaFBP jar file", "javaFBPJarFile"); propertyDescriptions .put("DrawFBP Help jar file", "jhallJarFile"); propertyDescriptions .put("Additional Component Jar Files", "additionalJarFiles"); } void displayProperties() { final JFrame jf = new JFrame(); jf.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent ev) { jf.dispose(); } }); JPanel panel = new JPanel(new GridBagLayout()); JScrollPane jsp = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); jf.setFocusable(true); jf.requestFocusInWindow(); jf.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent ev) { if (ev.getKeyCode() == KeyEvent.VK_ESCAPE) { jf.dispose(); } } }); panel.setBackground(Color.GRAY); panel.setLocation(frame.getX() + 50, frame.getY() + 50); panel.setSize(1200, 800); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); panel.setLayout(gbl); gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 0.5; gbc.weighty = 0.5; gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; JTextField[] tft = new JTextField[4]; tft[0] = new JTextField(" Property Descriptions"); tft[1] = new JTextField(" Property "); tft[2] = new JTextField(" Current Value "); tft[3] = new JTextField(" Starting Value (if different)"); tft[0].setFont(fontg); tft[1].setFont(fontg); tft[2].setFont(fontg); tft[3].setFont(fontg); displayRow(gbc, gbl, tft, panel, Color.BLUE); for (String p : propertyDescriptions.keySet()) { tft[0] = new JTextField(p); String q = propertyDescriptions.get(p); tft[1] = new JTextField(q); String u = properties.get(q); String w = ""; int i; if (u != null) w = u; boolean done = true; boolean first = true; while (true) { String v = ""; if (u == null) u = "(null)"; else { if (q.equals("additionalJarFiles") && first){ first = false; continue; } if ((i = w.indexOf(";")) > -1) { u = w.substring(0, i); w = w.substring(i + 1); done = false; } else { u = w; done = true; } v = startProperties.get(q); if (v == null) v = "(null)"; else if (v.equals(properties.get(q)) || v == null) v = ""; } if (q.equals("defaultCompLang")) { if (!(u.equals("(null)"))) { u = findGLFromLabel(u).showLangs(); if (!(v.equals(""))) v = findGLFromLabel(v).showLangs(); } } tft[2] = new JTextField(u); tft[3] = new JTextField(v); tft[0].setFont(fontg); tft[1].setFont(fontg); tft[2].setFont(fontf); tft[3].setFont(fontf); displayRow(gbc, gbl, tft, panel, Color.BLACK); if (done) break; tft[0] = new JTextField(""); tft[1] = new JTextField(""); } } //jsp.add(panel); jf.add(jsp); jf.pack(); Point p = frame.getLocation(); jf.setLocation(p.x + 150, p.y + 50); //int height = 200 + properties.size() * 40; jf.setSize(1200, 800); //jsp.setVisible(true); panel.setVisible(true); jf.setVisible(true); jf.toFront(); // jdialog.validate(); jsp.repaint(); panel.repaint(); jf.repaint(); frame.repaint(); } SelectionArea getNewArea() { SelectionArea sa = new SelectionArea(); sa.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true); sa.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( escapeKS, "CLOSE"); sa.getInputMap().put(escapeKS, "CLOSE"); sa.getActionMap().put("CLOSE", escapeAction); return sa; } File openAction(String fn) { File file = null; if (fn != null) file = new File(fn); String fname = fn; int i = jtp.getTabCount(); //ButtonTabComponent b = (ButtonTabComponent) jtp.getTabComponentAt(i); //curDiag = b.diag; if (i > 1 || curDiag.diagFile != null || curDiag.changed) getNewDiag(); jtp.setSelectedIndex(curDiag.tabNum); file = curDiag.open(file); if (file == null) { //CloseTabAction closeTabAction = new CloseTabAction(); //closeTabAction.actionPerformed(new ActionEvent(jtp, 0, "CLOSE")); closeTab(); //curDiag = null; return null; } fname = file.getName(); curDiag.diagFile = file; GenLang gl = null; String suff = curDiag.getSuffix(fname); if (suff.equals("fbp")) { gl = findGLFromLabel("FBP"); CodeManager cm = new CodeManager(curDiag); cm.display(file, gl); return file; } if (!(suff.equals("drw"))) { gl = findGLFromLanguage(suff); CodeManager cm = new CodeManager(curDiag); cm.display(file, gl); return file; } curDiag.title = fname; if (curDiag.title.toLowerCase().endsWith(".drw")) curDiag.title = curDiag.title.substring(0, curDiag.title.length() - 4); frame.setTitle("Diagram: " + curDiag.title); // curDiag.tabNum = i; jtp.setSelectedIndex(curDiag.tabNum); frame.repaint(); return file; } void saveAction(boolean saveAs) { File file = null; if (curDiag.diagFile == null) saveAs = true; if (!saveAs) file = curDiag.diagFile; file = curDiag.genSave(file, fCPArray[DIAGRAM], null); int i = jtp.getSelectedIndex(); if (file == null) { return; } jtp.setSelectedIndex(i); //curDiag.tabNum = i; curDiag.title = file.getName(); curDiag.diagFile = file; if (curDiag.title.toLowerCase().endsWith(".drw")) curDiag.title = curDiag.title.substring(0, curDiag.title.length() - 4); File currentDiagramDir = file.getParentFile(); frame.setTitle("Diagram: " + curDiag.title); properties .put("currentDiagramDir", currentDiagramDir.getAbsolutePath()); propertiesChanged = true; curDiag.changed = false; frame.repaint(); } /* static String makeRelFileName(String current, String parent) { if (!(current.startsWith("/") || current.substring(1, 2).equals(":"))) { return current; } String res = ""; String cur = current.replace('\\', '/'); String curLead; String par = parent.replace('\\', '/'); String parLead; while (true) { int i = par.indexOf("/"); if (i == -1) break; par = par.substring(i + 1); res += "../"; } int is = 0, js = 0; int i = 0; par = parent.replace('\\', '/'); // restore full length par while (true) { i = cur.indexOf("/", is); if (i == -1) break; curLead = cur.substring(0, i); int j = par.indexOf("/", js); if (j == -1) break; parLead = par.substring(0, j); if (!(parLead.equals(curLead))) break; res = res.substring(3); is = i + 1; js = j + 1; } return res + cur.substring(is); } */ static String makeAbsFileName(String current, String parent) { if (current.equals("")) return parent; if (current.startsWith("/")) return current; if (current.length() > 1 && current.substring(1, 2).equals(":")) return current; String cur = current.replace('\\', '/'); String par = parent.replace('\\', '/'); int k = 0; int m = 0; while (true) { if (cur.length() >= 3 && cur.substring(k, k + 3).equals("../")) { k += 3; m++; continue; } if (cur.length() >= 2 && cur.substring(k, k + 2).equals("./")) { k += 2; m++; continue; } break; } // int j = par.lastIndexOf("/"); // par = par.substring(0, j); for (int n = 0; n < m; n++) { int j = par.lastIndexOf("/"); if (j == -1) return current; par = par.substring(0, j); } return par + "/" + cur.substring(k); } public static BufferedImage readImageFromFile(File file) throws IOException { return ImageIO.read(file); } public void menuDeselected(MenuEvent e) { } public void menuCanceled(MenuEvent e) { } void changeFonts() { fontChooser = new MyFontChooser(frame, this); chooseFonts(fontChooser); if (gFontChanged) { properties.put("generalFont", generalFont); propertiesChanged = true; jfl.setText("Fixed font: " + fixedFont + "; general font: " + generalFont); fontg = new Font(generalFont, Font.PLAIN, (int) defaultFontSize); adjustFonts(); frame.repaint(); repaint(); } if (fFontChanged) { properties.put("fixedFont", fixedFont); propertiesChanged = true; jfl.setText("Fixed font: " + fixedFont + "; general font: " + generalFont); fontf = new Font(fixedFont, Font.PLAIN, (int) defaultFontSize); adjustFonts(); frame.repaint(); repaint(); } return; } void chooseFonts(MyFontChooser fontChooser){ fontChooser.buildFontLists(); String s = fontChooser.getFixedFont(); if (s != null) { fixedFont = s; fFontChanged = true; } s = fontChooser.getGeneralFont(); if (s != null) { generalFont = s; gFontChanged = true; } fontChooser.done(); } private void changeFontSize() { Float[] selectionValues = {new Float(10), new Float(12), new Float(14), new Float(16), new Float(18), new Float(20), new Float(22)}; int j = 0; for (int i = 0; i < selectionValues.length; i++) { if (Float.compare(selectionValues[i].floatValue(), defaultFontSize) == 0) j = i; } Float fs = (Float) MyOptionPane.showInputDialog(frame, "Font size dialog", "Select a font size", MyOptionPane.PLAIN_MESSAGE, null, selectionValues, selectionValues[j]); if (fs == null) return; defaultFontSize = fs.floatValue(); fontg = fontg.deriveFont(fs); fontf = fontf.deriveFont(fs); jfs.setText("Font Size: " + defaultFontSize); adjustFonts(); frame.repaint(); properties.put("defaultFontSize", Float.toString(defaultFontSize)); propertiesChanged = true; MyOptionPane.showMessageDialog(frame, "Font size changed"); frame.repaint(); repaint(); } void adjustFonts() { fileMenu = new JMenu(" File "); editMenu = new JMenu(" Edit "); helpMenu = new JMenu(" Help "); //runMenu = new JMenu(" Run "); int j = jtp.getTabCount(); for (int i = 0; i < j; i++) { ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(i); b.label.setFont(fontf); } jtp.repaint(); //osg.setFont(fontg); jfl.setFont(fontg); jfs.setFont(fontg); jtp.setFont(fontg); zoom.setFont(fontg); jtf.setFont(fontg); pan.setFont(fontg); grid.setFont(fontg); scaleLab.setFont(fontg); fileMenu.setFont(fontg); editMenu.setFont(fontg); helpMenu.setFont(fontg); //runMenu.setFont(fontg); diagDesc.setFont(fontg); for (int i = 0; i < but.length; i++) { but[i].setFont(fontg); but[i].setFocusable(true); but[i].addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent ev) { if (ev.getKeyCode() == KeyEvent.VK_ENTER){ JRadioButton rb = (JRadioButton)ev.getSource(); rb.setSelected(true); setBlkType(rb.getText()); } } }); } UIDefaults def = UIManager.getLookAndFeelDefaults(); //Hashtable<String, Font> ht = new Hashtable<String, Font>(); final FontUIResource res = new FontUIResource(fontg); for (Enumeration<Object> e = def.keys(); e.hasMoreElements(); ) { Object item = e.nextElement(); if (item instanceof String) { String s = (String) item; //System.out.println(s + " - " + def.get(item)); if (def.get(item) instanceof Font) { //System.out.println(s + " - " + def.get(item)); def.put(s, res); // UIManager.put(item, fontg); // System.out.println(s + " - " + def.get(item)); } } } UIManager.put("Menu.font", fontg); UIManager.put("MenuBar.font", fontg); UIManager.put("MenuItem.font", fontg); UIManager.put("Label.font", fontf); for (Block block : curDiag.blocks.values()) { block.draw(osg); } for (Arrow arrow : curDiag.arrows.values()) { arrow.draw(osg); } if (depDialog != null) depDialog.setFont(fontf); /* for (Object item : ht.keySet()) { UIManager.put(item, fontg); // System.out.println(item + " - " + fontg); } */ // UIManager.put("Button.select", slateGray1); try { createMenuBar(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } frame.setJMenuBar(menuBar); frame.repaint(); } // between just checks that the value val is >= lim1 and <= lim2 - or the inverse static boolean between(int val, int lim1, int lim2) { return between(val, (double) lim1, (double) lim2); } static boolean between(int val, double lim1, double lim2) { boolean res; res = (val >= lim1 && val <= lim2 && lim1 < lim2) || (val >= lim2 && val <= lim1 && lim2 < lim1); return res; } boolean readPropertiesFile() { if (propertiesFile == null) { String uh = System.getProperty("user.home"); propertiesFile = new File(uh + File.separator + "DrawFBPProperties.xml"); if (!propertiesFile.exists()) return false; } BufferedReader in = null; String s = null; try { in = new BufferedReader(new FileReader(propertiesFile)); } catch (FileNotFoundException e) { return false; } while (true) { try { s = in.readLine(); } catch (IOException e) { } if (s == null) break; s = s.trim(); if (s.equals("<properties>") || s.equals("</properties>")) continue; if (s.startsWith("<?xml")) continue; int i = s.indexOf("<"); int j = s.indexOf(">"); if (i > -1 && j > -1 && j > i + 1) { String key = s.substring(i + 1, j); s = s.substring(j + 1); int k = s.indexOf("<"); String u = ""; if (k > 0) { if (!(key.equals("additionalJarFiles"))) { s = s.substring(0, k).trim(); properties.put(key, s); } else { s = s.substring(0, k).trim(); while (true) { int m = s.indexOf(";"); if (m == -1){ u = s; int n = u.indexOf(":"); if (n == -1) break; properties.put("addnl_jf_" + u.substring(0, n), u.substring(n + 1)); jarFiles.put(u.substring(0, n), u.substring(n + 1)); break; } else { u = s.substring(0, m); s = s.substring(m + 1); int n = u.indexOf(":"); if (n == -1) break; properties.put("addnl_jf_" + u.substring(0, n), u.substring(n + 1)); jarFiles.put(u.substring(0, n), u.substring(n + 1)); } } } } } } try { in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return true; } void writePropertiesFile() { BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(propertiesFile)); out.write("<?xml version=\"1.0\"?> \n"); out.write("<properties> \n"); for (String k : properties.keySet()) { if (k.startsWith("addnl_jf_") || k.startsWith("additionalJarFiles")) continue; String s = "<" + k + "> " + properties.get(k) + "</" + k + "> \n"; out.write(s); } Iterator<Entry<String, String>> entries = jarFiles.entrySet().iterator(); String z = ""; String cma = ""; while (entries.hasNext()) { Entry<String, String> thisEntry = entries.next(); z += cma + thisEntry.getKey() + ":" + thisEntry.getValue(); cma = ";"; } String s = "<additionalJarFiles> " + z + "</additionalJarFiles> \n"; out.write(s); out.write("</properties> \n"); // Close the BufferedWriter out.flush(); out.close(); } catch (FileNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } boolean getJavaFBPJarFile() { if (javaFBPJarFile == null) { javaFBPJarFile = properties.get("javaFBPJarFile"); } File jf = null; boolean res = true; if (javaFBPJarFile != null) { jf = new File(javaFBPJarFile); } if (jf != null && jf.exists()) { //jarFiles.put("JavaFBP Jar File", jf.getAbsolutePath()); return res; } String msg = null; if (jf != null) { if (!jf.exists()) msg = "Unable to read JavaFBP jar file: " + javaFBPJarFile; } else msg = "JavaFBP jar file missing"; if (msg != null) MyOptionPane.showMessageDialog(frame, msg, MyOptionPane.ERROR_MESSAGE); int response = MyOptionPane.showConfirmDialog(frame, "Specify a JavaFBP jar file", "Locate JavaFBP jar file", MyOptionPane.OK_CANCEL_OPTION /*, MyOptionPane.PLAIN_MESSAGE */); if (response == MyOptionPane.OK_OPTION) res = locateJavaFBPJarFile(); else { MyOptionPane.showMessageDialog(frame, "No JavaFBP jar file located", MyOptionPane.ERROR_MESSAGE); res = false; } return res; } String getSelFile(MyFileChooser fc) { String[] sa = new String[1]; fc.getSelectedFile(sa); // getSelectedFile puts result in sa[0] return sa[0]; } boolean locateJavaFBPJarFile() { String s = properties.get("javaFBPJarFile"); File f = null; if (s == null) f = new File(System.getProperty("user.home")); else f = (new File(s)).getParentFile(); MyFileChooser fc = new MyFileChooser(f, fCPArray[JARFILE]); int returnVal = fc.showOpenDialog(); File cFile = null; if (returnVal == MyFileChooser.APPROVE_OPTION) { cFile = new File(getSelFile(fc)); if (cFile == null || !(cFile.exists())) { MyOptionPane.showMessageDialog(frame, "Unable to read JavaFBP jar file " + cFile.getName(), MyOptionPane.ERROR_MESSAGE); return false; } // diag.driver.currentDir = new File(cFile.getParent()); javaFBPJarFile = cFile.getAbsolutePath(); properties.put("javaFBPJarFile", javaFBPJarFile); propertiesChanged = true; MyOptionPane.showMessageDialog(frame, "JavaFBP jar file location: " + cFile.getAbsolutePath(), MyOptionPane.INFORMATION_MESSAGE); //jarFiles.put("JavaFBP Jar File", cFile.getAbsolutePath()); for (int i = 0; i < driver.jtp.getTabCount(); i++) { ButtonTabComponent b = (ButtonTabComponent) driver.jtp .getTabComponentAt(i); Diagram d = b.diag; if (d == null) continue; for (Block bk : d.blocks.values()) { bk.getClassInfo(bk.fullClassName); } } return true; } return false; } boolean addAdditionalJarFile(){ String ans = (String) MyOptionPane.showInputDialog(frame, "Enter Description of jar file being added", "Enter Description", MyOptionPane.PLAIN_MESSAGE, null, null, null); if (ans == null || ans.equals("")){ MyOptionPane.showMessageDialog(frame, "No description entered", MyOptionPane.ERROR_MESSAGE); return false; } String s = properties.get("javaFBPJarFile"); File f = null; if (s == null) f = new File(System.getProperty("user.home")); else f = (new File(s)).getParentFile(); MyFileChooser fc = new MyFileChooser(f, fCPArray[JARFILE]); int returnVal = fc.showOpenDialog(); File cFile = null; if (returnVal == MyFileChooser.APPROVE_OPTION) { cFile = new File(getSelFile(fc)); if (cFile == null || !(cFile.exists())) { MyOptionPane.showMessageDialog(frame, "Unable to read additional jar file " + cFile.getName(), MyOptionPane.ERROR_MESSAGE); return false; } jarFiles.put(ans, cFile.getAbsolutePath()); @SuppressWarnings("rawtypes") Iterator entries = jarFiles.entrySet().iterator(); String t = ""; String cma = ""; while (entries.hasNext()) { @SuppressWarnings("unchecked") Entry<String, String> thisEntry = (Entry<String, String>) entries.next(); t += cma + thisEntry.getKey() + ":" + thisEntry.getValue(); cma = ";"; } properties.put("additionalJarFiles", t); propertiesChanged = true; } return true; } boolean locateJhallJarFile() { String s = properties.get("jhallJarFile"); File f = null; if (s == null) f = new File(System.getProperty("user.home")); else f = (new File(s)).getParentFile(); MyFileChooser fc = new MyFileChooser(f, fCPArray[JHALL]); int returnVal = fc.showOpenDialog(); File cFile = null; if (returnVal == MyFileChooser.APPROVE_OPTION) { cFile = new File(getSelFile(fc)); if (cFile == null || !(cFile.exists())) { MyOptionPane.showMessageDialog(frame, "Unable to read DrawFBP Help jar file " + cFile.getName()); return false; } // diag.driver.currentDir = new File(cFile.getParent()); jhallJarFile = cFile.getAbsolutePath(); properties.put("jhallJarFile", jhallJarFile); propertiesChanged = true; MyOptionPane.showMessageDialog(frame, "DrawFBP Help jar file location: " + cFile.getAbsolutePath()); return true; } else return false; } void closeTab() { closeTabAction.actionPerformed(new ActionEvent(jtp, 0, "CLOSE")); } public static final void copyInputStream(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) >= 0) { // System.out.println(new String(buffer)); out.write(buffer, 0, len); } out.flush(); in.close(); out.close(); } void displayRow(GridBagConstraints gbc, GridBagLayout gbl, JTextField[] tf, JPanel panel, Color col) { gbc.gridx = 0; gbc.weightx = 0.25; for (int i = 0; i < 4; i++) { if (i > 1) gbc.weightx = 0.5; gbl.setConstraints(tf[i], gbc); tf[i].setBackground(lg); tf[i].setForeground(col); gbc.gridx++; panel.add(tf[i]); tf[i].setEditable(false); } gbc.gridy++; } /* public final void getSamples() { Enumeration<?> entries; ZipFile zipFile; MyOptionPane.showMessageDialog(frame, "Select new project for sample networks"); // zip file must have "src", "test" and "diagrams" directories // and optionally components... String zipname = "FBPSamples.zip"; InputStream is = this.getClass().getClassLoader() .getResourceAsStream(zipname); String zfn = System.getProperty("user.home") + File.separator + zipname; File f = new File(zfn); String s = f.getParent(); if (f.exists()) f.delete(); if (s != null) (new File(s)).mkdirs(); try { copyInputStream(is, new FileOutputStream(f)); } catch (IOException e) { } try { zipFile = new ZipFile(zfn); entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry) entries.nextElement(); if (entry.isDirectory()) { // Assume directories are stored parents first then // children. System.out.println("Extracting directory: " + entry.getName()); // This is not robust, just for demonstration purposes. (new File(entry.getName())).mkdirs(); } else { System.out.println("Extracting file: " + entry.getName()); f = new File(entry.getName()); if (f.exists()) f.delete(); copyInputStream(zipFile.getInputStream(entry), new FileOutputStream(f)); } } zipFile.close(); } catch (IOException ioe) { System.err.println("Unhandled exception:"); ioe.printStackTrace(); return; } } */ void checkCompatibility(Arrow a) { Arrow a2 = a.findArrowEndingAtBlock(); Block from = curDiag.blocks.get(new Integer(a.fromId)); Block to = curDiag.blocks.get(new Integer(a2.toId)); // String downPort = a2.downStreamPort; a.checkStatus = Status.UNCHECKED; if (!(from instanceof ProcessBlock) || !(to instanceof ProcessBlock)) return; if (a.upStreamPort == null || a.upStreamPort.equals("")) return; if (a2.downStreamPort == null || a2.downStreamPort.equals("")) return; if (a.upStreamPort.equals("*") || a2.downStreamPort.equals("*")) { a.checkStatus = Status.COMPATIBLE; return; } if (from.outputPortAttrs == null || to.inputPortAttrs == null) return; AOutPort ao = from.outputPortAttrs.get(from.stem(a.upStreamPort)); if (ao == null) return; AInPort ai = to.inputPortAttrs.get(to.stem(a2.downStreamPort)); if (ai == null) return; if (ai.type.isAssignableFrom(ao.type) || ao.type == Object.class) // Object // class // is // default a.checkStatus = Status.COMPATIBLE; else a.checkStatus = Status.INCOMPATIBLE; } /* * Test if point (xp, yp) is "near" line defined by (x1, y1) and (x2, y2) */ boolean nearpln(int xp, int yp, int x1, int y1, int x2, int y2) { Rectangle2D r = new Rectangle2D.Double(xp - gridUnitSize * scalingFactor, yp - gridUnitSize * scalingFactor, gridUnitSize * 2 * scalingFactor, gridUnitSize * 2 * scalingFactor); Line2D line = new Line2D.Float(x1, y1, x2, y2); return line.intersects(r); } java.awt.geom.Point2D.Double findIntersectPoint(Line2D.Float ln, int x3, int y3, int x4, int y4) { double x1 = ln.getX1(); double x2 = ln.getX2(); double y1 = ln.getY1(); double y2 = ln.getY2(); double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); if (d == 0) return null; double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d; double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d; return new Point2D.Double(xi, yi); } void processSubnetPort(Arrow arr) { SubnetPort snPort = null; DrawFBP.Side s = null; Point2D.Double p = null; Line2D.Float line; int left = curDiag.cEncl.leftEdge; // for legibility int right = curDiag.cEncl.rgtEdge; int top = curDiag.cEncl.topEdge; int bottom = curDiag.cEncl.botEdge; int x = arr.fromX; int y = arr.fromY; if (arr.bends != null) { for (Bend b : arr.bends) { line = new Line2D.Float(x, y, b.x, b.y); if (line.intersectsLine(left, top, left, bottom)) { p = findIntersectPoint(line, left, top, left, bottom); s = DrawFBP.Side.LEFT; } else if (line.intersectsLine(right, top, right, bottom)) { p = findIntersectPoint(line, right, top, right, bottom); s = DrawFBP.Side.RIGHT; } if (s != null) break; } } if (s == null) { line = new Line2D.Float(x, y, arr.toX, arr.toY); if (line.intersectsLine(left, top, left, bottom)) { p = findIntersectPoint(line, left, top, left, bottom); s = DrawFBP.Side.LEFT; } else if (line.intersectsLine(right, top, right, bottom)) { p = findIntersectPoint(line, right, top, right, bottom); s = DrawFBP.Side.RIGHT; } } if (s == null) { curDiag.findArrowCrossing = false; curDiag.cEncl = null; return; } for (SubnetPort snp : curDiag.cEncl.subnetPorts) { if (snp.y >= p.y - 4 && snp.y <= p.y + 4 && snp.side == s) snPort = snp; } if (snPort == null) { snPort = new SubnetPort((int) p.y, s); curDiag.cEncl.subnetPorts.add(snPort); } if (curDiag.cEncl.editPortName) { String ans = (String) MyOptionPane.showInputDialog(frame, "Enter or change text", "Edit subnet port name", MyOptionPane.PLAIN_MESSAGE, null, null, snPort.name); if (ans != null/* && ans.length() > 0*/) snPort.name = ans; curDiag.cEncl.editPortName = false; } if (curDiag.cEncl.changeSubstreamSensitivity) { snPort.substreamSensitive = !snPort.substreamSensitive; curDiag.cEncl.changeSubstreamSensitivity = false; } curDiag.findArrowCrossing = false; curDiag.cEncl = null; repaint(); } void displayAlignmentLines(Block block) { if (!(block instanceof ProcessBlock)) return; block.hNeighbour = null; for (Block b : curDiag.blocks.values()) { if (!(b instanceof ProcessBlock)) continue; int y = b.cy + b.height / 2; if (b != block && between(block.cy + block.height / 2, y - 6, y + 6)) { block.hNeighbour = b; break; } } block.vNeighbour = null; for (Block b : curDiag.blocks.values()) { if (!(b instanceof ProcessBlock)) continue; int x = b.cx - b.width / 2; if (b != block && between(block.cx - block.width / 2, x - 6, x + 6)) { block.vNeighbour = b; break; } } } Point gridAlign(Point p) { Point p2 = p; if (curDiag.clickToGrid) { int x = ((int) (p.getX() + gridUnitSize / 2) / gridUnitSize) * gridUnitSize; int y = ((int) (p.getY() + gridUnitSize / 2) / gridUnitSize) * gridUnitSize; p2 = new Point(x, y); } return p2; } GenLang findGLFromLabel(String s) { for (int i = 0; i < genLangs.length; i++) if (genLangs[i].label.equals(s)) return genLangs[i]; return null; } GenLang findGLFromLanguage(String s) { for (int i = 0; i < genLangs.length; i++) for (int j = 0; j < genLangs[i].langs.length; j++) if (genLangs[i].langs[j].extn.equals(s)) return genLangs[i]; return null; } static public void applyOrientation(Component c) { c.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); if (c instanceof JMenu) { JMenu menu = (JMenu) c; int ncomponents = menu.getMenuComponentCount(); for (int i = 0; i < ncomponents; ++i) { applyOrientation(menu.getMenuComponent(i)); } } else if (c instanceof Container) { Container container = (Container) c; int ncomponents = container.getComponentCount(); for (int i = 0; i < ncomponents; ++i) { applyOrientation(container.getComponent(i)); } } } public void stateChanged(ChangeEvent e) { JSlider source = (JSlider) e.getSource(); //oldW = getSize().width; //oldH = getSize().height; if (!source.getValueIsAdjusting()) { scalingFactor = ((int) source.getValue()) / 100.0; String scale = (int) source.getValue() + "%"; scaleLab.setText(scale); frame.pack(); frame.setPreferredSize(new Dimension(1200, 800)); frame.repaint(); } } public void componentHidden(ComponentEvent arg0) { // TODO Auto-generated method stub } public void componentMoved(ComponentEvent arg0) { // TODO Auto-generated method stub } public void componentResized(ComponentEvent e) { Dimension dim = this.getSize(); Dimension dim2 = new Dimension(dim.width / but.length, dim.height); int no = but.length; for (int j = 0; j < no; j++) { box21.remove(0); but[j].setMaximumSize(dim2); box21.add(but[j]); } //dim2.width = 50; //but[4].setMinimumSize(dim2); box21.repaint(); } public void componentShown(ComponentEvent arg0) { // TODO Auto-generated method stub } public static void main(String[] args) { // System.out.println("Locale: " + Locale.getDefault() + "\n"); // String osName = System.getProperty("os.name"); // System.out.print("OS name: " + osName + "\n"); String laf = UIManager.getSystemLookAndFeelClassName(); // String nimbusLaf = null; /* * //if (!(osName.startsWith("Win"))) { for (LookAndFeelInfo info : * UIManager.getInstalledLookAndFeels()) { * //System.out.print("Look and feel: " + info.getName() + "\n"); if * ("Nimbus".equals(info.getName())) nimbusLaf = info.getClassName(); * //else // laf = info.getClassName(); } //} * * if (nimbusLaf != null) { laf = nimbusLaf; // * System.out.print("Look and feel: Nimbus\n"); } else */ // System.out.print("Look and feel: System \n"); System.setProperty("apple.laf.useScreenMenuBar", "true"); try { UIManager.setLookAndFeel(laf); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } catch (InstantiationException e1) { e1.printStackTrace(); } catch (IllegalAccessException e1) { e1.printStackTrace(); } catch (UnsupportedLookAndFeelException e1) { e1.printStackTrace(); } JFrame.setDefaultLookAndFeelDecorated(true); new DrawFBP(args); } public class Lang { String language; // this is the language... String extn; // extension - excluding period Lang(String lan, String ex) { language = lan; extn = ex; } } public class GenLang { // this class really refers more to a VM than a language... (ex. that // fbp notation is treated as a language) String label; // String genCodeFileName; String suggExtn; // excluding period - suggested extension when // generating code... String srcDirProp; // DrawFBP property specifying source directory String netDirProp; // DrawFBP property specifying source directory for // net definition FileFilter filter; Lang[] langs; // each entry has a language name, and an extension - // excluding periods GenLang(String lan, String se, FileFilter f) { label = lan; suggExtn = se; srcDirProp = "current" + label + "SourceDir"; netDirProp = "current" + label + "NetworkDir"; if (label.equals("C#")) { srcDirProp = "currentCsharpSourceDir"; netDirProp = "currentCsharpNetworkDir"; // xml does not seem to like #'s } filter = f; } String showLangs() { String s = ""; for (int i = 0; i < langs.length; i++) { if (i == 1) s += " (+ "; if (i > 1) s += ", "; s += langs[i].language; if (i > 0 && i == (langs.length - 1)) s += ")"; } return s; } String showSuffixes() { String s = "("; for (int i = 0; i < langs.length; i++) { if (i > 0) s += ", "; s += "*." + langs[i].extn; } return s + ")"; } } public class FileChooserParms { String name; String propertyName; String prompt; String fileExt; FileFilter filter; String title; FileChooserParms(String x, String a, String b, String c, FileFilter d, String e) { name = x; propertyName = a; prompt = b; fileExt = c; filter = d; title = e; } } public class CloseAppAction extends AbstractAction { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { boolean close = true; for (int i = 0; i < jtp.getTabCount(); i++) { ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(i); Diagram diag = b.diag; if (diag != null) { if (!diag.askAboutSaving()) { close = false; break; } } } //if (propertiesChanged) { writePropertiesFile(); //} if (close) { frame.dispose(); System.exit(0); } } } public class CloseTabAction extends AbstractAction { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { int i = jtp.getSelectedIndex(); if (i == -1) return; ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(i); Diagram diag = b.diag; if (diag != null) { if (!diag.askAboutSaving()) return; } jtp.removeTabAt(i); driver.properties.remove("currentDiagram"); int j = jtp.getTabCount(); if (j == 0) { // make one tab with "(untitled)" // Diagram curDiag = new Diagram(driver); getNewDiag(); frame.setTitle("Diagram: (untitled)"); } else { jtp.setSelectedIndex(j - 1); b = (ButtonTabComponent) jtp .getTabComponentAt(j - 1); curDiag = b.diag; for (int k = i; k < j; k++) { b = (ButtonTabComponent) jtp.getTabComponentAt(k); diag = b.diag; diag.tabNum = k; } } frame.repaint(); } } public class EscapeAction extends AbstractAction { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { if (curDiag.currentArrow != null) { Integer aid = new Integer(curDiag.currentArrow.id); curDiag.arrows.remove(aid); curDiag.currentArrow = null; // terminate arrow drawing repaint(); return; } if (e.getSource() == jHelpViewer){ popup2.dispose(); repaint(); return; } if (-1 < jtp.getSelectedIndex()) { closeTab(); //else { ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(0); JLabel j = (JLabel) b.getComponent(0); String s = j.getText(); if ( 1 == jtp.getTabCount() && (s.equals("(untitled)") || s.equals("")) && MyOptionPane.YES_OPTION == MyOptionPane.showConfirmDialog(frame, "Choose one option", "Leave DrawFBP?", MyOptionPane.YES_NO_OPTION)) { closeAppAction .actionPerformed(new ActionEvent(jtp, 0, "CLOSE")); } } } } public class JavaFileFilter extends FileFilter { @Override public boolean accept(File f) { String s = f.getName().toLowerCase(); return s.toLowerCase().endsWith(".java") || s.toLowerCase().endsWith(".scala") || s.toLowerCase().endsWith(".groovy") || f.isDirectory(); } @Override public String getDescription() { return "Java source files (*.java, *.scala, *.groovy)"; } } public class JavaGenFilter extends FileFilter { @Override public boolean accept(File f) { String s = f.getName().toLowerCase(); return s.toLowerCase().endsWith(".java") || f.isDirectory(); } @Override public String getDescription() { return "Java source files (*.java)"; } } public class CsharpFileFilter extends FileFilter { @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith(".cs") || f.isDirectory(); } @Override public String getDescription() { return "C# source files (*.cs)"; } } public class JSONFilter extends FileFilter { @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith(".json") || f.isDirectory(); } @Override public String getDescription() { return "JSON source files (*.json)"; } } /* * public class NoFloGenFilter extends FileFilter { * * @Override public boolean accept(File f) { * * return f.getName().toLowerCase().endsWith(".json") || f.isDirectory(); * * } * * @Override public String getDescription() { return * "NoFlo source files (*.json)"; } } */ public class FBPFilter extends FileFilter { @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith(".fbp") || f.getName().toLowerCase().endsWith("package.json") || f.isDirectory(); } @Override public String getDescription() { return "FBP diagram files (*.fbp)"; } } public class JavaClassFilter extends FileFilter { @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith(".class") || f.isDirectory(); } @Override public String getDescription() { return "Java class files (*." + "class" + ")"; } } public class DiagramFilter extends FileFilter { @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith(".drw") || f.getName().toLowerCase().endsWith(".dr~") || f.getName().toLowerCase().endsWith(".fbp") || f.getName().toLowerCase().endsWith("package.json") // package.json added to remind us that this is like a // directory || f.getName().toLowerCase().endsWith(".json") || f.isDirectory(); } @Override public String getDescription() { return "Diagrams (*.drw)"; } } public class JarFileFilter extends FileFilter { @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith(".jar") || f.isDirectory(); } @Override public String getDescription() { return "Jar files (*." + "jar" + ")"; } } // Filter for images public class ImageFilter extends FileFilter { @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith(".png") || f.getName().toLowerCase().endsWith(".jpg") || f.getName().toLowerCase().endsWith(".bmp") || f.isDirectory(); } @Override public String getDescription() { return "Images (*.png, *.jpg, *.bmp)"; } } public class SelectionArea extends JComponent implements MouseInputListener { static final long serialVersionUID = 111L; int oldx, oldy, mousePressedX, mousePressedY; public SelectionArea() { setOpaque(true); addMouseListener(this); addMouseMotionListener(this); // setFont(fontg); setBackground(Color.WHITE); setPreferredSize(new Dimension(4000, 3000)); // experimental } public void paint(Graphics g) { // Paint background if we're opaque. //osg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // RenderingHints.VALUE_ANTIALIAS_ON); RenderingHints rh = new RenderingHints( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); rh.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); rh.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); rh.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); osg.setRenderingHints(rh); if (isOpaque()) { //osg.setColor(getBackground()); osg.setColor(Color.WHITE); osg.fillRect(0, 1, (int) (getWidth()/scalingFactor), (int) (getHeight()/scalingFactor - 1)); } int i = jtp.getSelectedIndex(); ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(i); Diagram diag = b.diag; // if (curDiag != diag) { // int x = 0; // problem! // } grid.setSelected(diag.clickToGrid); repaint(); for (Block block : diag.blocks.values()) { block.draw(osg); } for (Arrow arrow : diag.arrows.values()) { arrow.draw(osg); } String s = diag.desc; if (s != null) s = s.replace('\n', ' '); else s = " "; diagDesc.setText(s); Graphics2D g2d = (Graphics2D) g; g2d.scale(scalingFactor, scalingFactor); //g2d.translate(xTranslate, yTranslate); // Now copy that off-screen image onto the screen g2d.drawImage(buffer, 0, 0 , null); } FoundPoint findArrowStart(int xa, int ya) { FoundPoint fp = null; for (Block block : curDiag.blocks.values()) { if (!(between(xa, block.leftEdge - 6 * scalingFactor, block.rgtEdge + 6 * scalingFactor))) continue; if (!(between(ya, block.topEdge - 4 * scalingFactor, block.botEdge + 4 * scalingFactor))) continue; /* check for possible start of arrows */ if (between(xa, block.leftEdge - 6 * scalingFactor, block.leftEdge + 6 * scalingFactor) && between(ya, block.topEdge, block.botEdge)) { fp = new FoundPoint(block.leftEdge, ya, Side.LEFT, block); break; } if (between(xa, block.rgtEdge - 6 * scalingFactor, block.rgtEdge + 6 * scalingFactor) && between(ya, block.topEdge, block.botEdge)) { fp = new FoundPoint(block.rgtEdge, ya, Side.RIGHT, block); break; } if (between(ya, block.topEdge - 4 * scalingFactor, block.topEdge + 4 * scalingFactor) && between(xa, block.leftEdge, block.rgtEdge)) { fp = new FoundPoint(xa, block.topEdge, Side.TOP, block); break; } if (between(ya, block.botEdge - 4 * scalingFactor, block.botEdge + 4 * scalingFactor) && between(xa, block.leftEdge, block.rgtEdge)) { fp = new FoundPoint(xa, block.botEdge, Side.BOTTOM, block); break; } } return fp; } public void mouseMoved(MouseEvent e) { int i = jtp.getSelectedIndex(); if (i == -1) return; ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(i); curDiag = b.diag; int x = (int) Math.round(e.getX() / scalingFactor); int y = (int) Math.round(e.getY() / scalingFactor); int xa, ya; arrowRoot = null; if (panSwitch) { Rectangle r = curDiag.area.getBounds(); r = new Rectangle(r.x, r.y, r.width - 20, r.height - 40); if (r.contains(x, y)) frame.setCursor(openPawCursor); else frame.setCursor(defaultCursor); } Point p = new Point(x, y); p = gridAlign(p); xa = (int) p.getX(); ya = (int) p.getY(); if (enclSelForArrow != null) { enclSelForArrow.corner = null; enclSelForArrow = null; repaint(); return; } selBlockM = null; // look for corner of an enclosure - if corner not null, you will see diagonal arrows at corners for (Block block : curDiag.blocks.values()) { // block.calcEdges(); if (block instanceof Enclosure) { Enclosure enc = (Enclosure) block; if (between(xa, block.leftEdge - 6, block.leftEdge + 6) && between(ya, block.topEdge - 6, block.topEdge + 6)) { enclSelForArrow = enc; enc.corner = Corner.TOPLEFT; break; } if (between(xa, block.leftEdge - 6, block.leftEdge + 6) && between(ya, block.botEdge - 6, block.botEdge + 6)) { enclSelForArrow = enc; enc.corner = Corner.BOTTOMLEFT; break; } if (between(xa, block.rgtEdge - 6, block.rgtEdge + 6) && between(ya, block.topEdge - 6, block.topEdge + 6)) { enclSelForArrow = enc; enc.corner = Corner.TOPRIGHT; break; } if (between(xa, block.rgtEdge - 6, block.rgtEdge + 6) && between(ya, block.botEdge - 6, block.botEdge + 6)) { enclSelForArrow = enc; enc.corner = Corner.BOTTOMRIGHT; break; } } // logic to change cursor to drag_icon int hh = gFontHeight; boolean udi; if (block.type.equals(Block.Types.ENCL_BLOCK)) { udi = between(xa, block.leftEdge + block.width / 5, block.rgtEdge - block.width / 5) && between(ya, block.topEdge - hh, block.topEdge + hh / 2); } else { udi = between(xa, block.leftEdge + 6 * scalingFactor, block.rgtEdge - 6 * scalingFactor) && between(ya, block.topEdge + 6 * scalingFactor, block.botEdge - 6 * scalingFactor); } if (udi) { selBlockM = block; // mousing select if (!use_drag_icon) { if (curDiag.jpm == null && !panSwitch) frame.setCursor(drag_icon); use_drag_icon = true; } break; } } if (selBlockM == null) { if (use_drag_icon) use_drag_icon = false; if (!panSwitch) frame.setCursor(defaultCursor); } //curDiag.foundBlock = null; FoundPoint fp = findArrowStart(xa, ya); if (fp != null) arrowRoot = fp; repaint(); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } /* * The following mouse actions are supported: * * - click on block - highlights block * - double-click on block - brings up popup menu if not subnet * - brings up subnet if subnet * - press on side of block starts arrow * - release on side of block starts or ends arrow * - click on arrow - brings up popup menu * - press on block - starts drag * */ public void mousePressed(MouseEvent e) { int i = jtp.getSelectedIndex(); if (i == -1) return; ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(i); curDiag = b.diag; Side side = null; leftButton = (e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK; int x = e.getX(); x = (int) Math.round(x / scalingFactor); int y = e.getY(); y = (int) Math.round(y / scalingFactor); int xa, ya; xa = x; ya = y; curx = xa; cury = ya; if (curDiag.jpm != null) { curDiag.jpm.setVisible(false); curDiag.jpm = null; frame.repaint(); return; } if (panSwitch) { //Rectangle r = curDiag.area.getBounds(); Dimension d = curDiag.area.getSize(); //if (r.contains(x, y)) { if (x >= curDiag.area.getX() && x <= curDiag.area.getX() + d.width && y >= curDiag.area.getY() && y <= curDiag.area.getY() + d.height) { frame.setCursor(closedPawCursor); panX = xa; panY = ya; return; } else frame.setCursor(defaultCursor); } if (e.getClickCount() == 2) return; curDiag.foundBlock = null; selBlock = null; selArrow = null; blockSelForDragging = null; //enclSelForDragging = null; //arrowEndForDragging = null; //bendForDragging = null; frame.repaint(); // look for side or corner of an enclosure for (Block block : curDiag.blocks.values()) { block.calcEdges(); if (block instanceof Enclosure) { Enclosure enc = (Enclosure) block; /* test for a hit within the rectangle at top */ int hh = gFontHeight; if (between(xa, block.leftEdge + block.width / 5, block.rgtEdge - block.width / 5) && between(ya, block.topEdge - hh, block.topEdge + hh / 2)) { mousePressedX = oldx = xa; mousePressedY = oldy = ya; blockSelForDragging = block; break; } /* now handle stretching at the corners */ if (between(xa, block.leftEdge - 6, block.leftEdge + 6) && between(ya, block.topEdge - 6, block.topEdge + 6)) { blockSelForDragging = enc; enc.corner = Corner.TOPLEFT; break; } if (between(xa, block.leftEdge - 6, block.leftEdge + 6) && between(ya, block.botEdge - 6, block.botEdge + 6)) { blockSelForDragging = enc; enc.corner = Corner.BOTTOMLEFT; break; } if (between(xa, block.rgtEdge - 6, block.rgtEdge + 6) && between(ya, block.topEdge - 6, block.topEdge + 6)) { blockSelForDragging = enc; enc.corner = Corner.TOPRIGHT; break; } if (between(xa, block.rgtEdge - 6, block.rgtEdge + 6) && between(ya, block.botEdge - 6, block.botEdge + 6)) { blockSelForDragging = enc; enc.corner = Corner.BOTTOMRIGHT; break; } } else { // not enclosure /* * the following leaves a strip around the outside of each * block that cannot be used for dragging! */ if (between(xa, block.leftEdge + 4 * scalingFactor, block.rgtEdge - 4 * scalingFactor) && between(ya, block.topEdge + 4 * scalingFactor, block.botEdge - 4 * scalingFactor)) { mousePressedX = oldx = xa; mousePressedY = oldy = ya; blockSelForDragging = block; break; } } /* check for possible starts of arrows */ if (between(xa, block.leftEdge - 4 * scalingFactor, block.leftEdge + 4 * scalingFactor) && between(ya, block.topEdge, block.botEdge)) { curDiag.foundBlock = block; xa = block.leftEdge; // ya = ya; side = Side.LEFT; break; } if (between(xa, block.rgtEdge - 4 * scalingFactor, block.rgtEdge + 4 * scalingFactor) && between(ya, block.topEdge, block.botEdge)) { curDiag.foundBlock = block; xa = block.rgtEdge; // ya = ya; side = Side.RIGHT; break; } if (between(ya, block.topEdge - 4 * scalingFactor, block.topEdge + 4 * scalingFactor) && between(xa, block.leftEdge, block.rgtEdge) && !(block instanceof Enclosure)) { curDiag.foundBlock = block; // xa = xa; ya = block.topEdge; side = Side.TOP; break; } if (between(ya, block.botEdge - 4 * scalingFactor, block.botEdge + 4 * scalingFactor) && between(xa, block.leftEdge, block.rgtEdge)) { curDiag.foundBlock = block; // xa = xa; ya = block.botEdge; side = Side.BOTTOM; break; } // } } if (blockSelForDragging != null && blockSelForDragging instanceof Enclosure) { ox = blockSelForDragging.cx; oy = blockSelForDragging.cy; ow = blockSelForDragging.width; oh = blockSelForDragging.height; repaint(); return; } /* if (curDiag.currentArrow != null) { if (between(xa,curDiag.currentArrow.toX - 4, curDiag.currentArrow.toX + 4) && between(ya,curDiag.currentArrow.toY - 4, curDiag.currentArrow.toY + 4)) { curDiag.currentArrow.toX = xa; curDiag.currentArrow.toY = ya; } else { Integer aid = new Integer(curDiag.currentArrow.id); curDiag.arrows.remove(aid); curDiag.foundBlock = null; curDiag.currentArrow = null; //repaint(); } repaint(); } */ // if no currentDiag.currentArrow, start an arrow if (curDiag.currentArrow == null && curDiag.foundBlock != null && arrowEndForDragging == null) { Arrow arrow = new Arrow(curDiag); selArrow = arrow; // selBlockP = null; arrow.fromX = xa; arrow.fromY = ya; arrow.fromId = curDiag.foundBlock.id; curDiag.currentArrow = arrow; arrow.lastX = xa; // save last x and y arrow.lastY = ya; Integer aid = new Integer(arrow.id); curDiag.arrows.put(aid, arrow); // curDiag.changed = true; //arrow.fromSide = side; //if (from != null) { if (side == Side.TOP) arrow.fromY = curDiag.foundBlock.cy - curDiag.foundBlock.height / 2; else if (side == Side.BOTTOM) arrow.fromY = curDiag.foundBlock.cy + curDiag.foundBlock.height / 2; else if (side == Side.LEFT) arrow.fromX = curDiag.foundBlock.cx - curDiag.foundBlock.width / 2; else if (side == Side.RIGHT) arrow.fromX = curDiag.foundBlock.cx + curDiag.foundBlock.width / 2; //} curDiag.foundBlock = null; } repaint(); } public void mouseDragged(MouseEvent e) { int i = jtp.getSelectedIndex(); if (i == -1) return; ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(i); curDiag = b.diag; int x = (int) Math.round(e.getX() / scalingFactor); int y = (int) Math.round(e.getY() / scalingFactor); int xa, ya; //curDiag.arrowRoot = null; Point p = new Point(x, y); p = gridAlign(p); xa = (int) p.getX(); ya = (int) p.getY(); if (e.getClickCount() == 2) { //blockSelForDragging = null; //enclSelForDragging = null; arrowEndForDragging = null; bendForDragging = null; } if (panSwitch) { for (Block block : curDiag.blocks.values()) { block.cx = block.cx + xa - panX; block.cy = block.cy + ya - panY; block.calcEdges(); } for (Arrow arrow : curDiag.arrows.values()) { arrow.fromX = arrow.fromX + xa - panX; arrow.fromY = arrow.fromY + ya - panY; arrow.toX = arrow.toX + xa - panX; arrow.toY = arrow.toY + ya - panY; if (arrow.bends != null) { for (Bend bend : arrow.bends) { bend.x = bend.x + xa - panX; bend.y = bend.y + ya - panY; } } } frame.repaint(); curDiag.changed = true; panX = xa; panY = ya; repaint(); return; } // if (!leftButton) // use left button for dragging // return; if (arrowEndForDragging != null) { Arrow arr = arrowEndForDragging; if (arr.tailMarked) { arr.fromId = -1; arr.fromX = xa; arr.fromY = ya; } else { arr.toId = -1; arr.toX = xa; arr.toY = ya; } curDiag.changed = true; repaint(); return; } if (bendForDragging != null) { bendForDragging.x = xa; bendForDragging.y = ya; curDiag.changed = true; repaint(); return; } // logic to drag one corner of enclosure if (blockSelForDragging != null && blockSelForDragging instanceof Enclosure) { Enclosure enc = (Enclosure) blockSelForDragging; if (enc.corner == Corner.TOPLEFT) { enc.width = ox + ow / 2 - xa; enc.height = oy + oh / 2 - ya; enc.cx = xa + enc.width / 2; enc.cy = ya + enc.height / 2; enc.calcEdges(); curDiag.changed = true; repaint(); return; } if (enc.corner == Corner.BOTTOMLEFT) { enc.width = ox + ow / 2 - xa; enc.height = ya - (oy - oh / 2); enc.cx = xa + enc.width / 2; enc.cy = ya - enc.height / 2; enc.calcEdges(); curDiag.changed = true; repaint(); return; } if (enc.corner == Corner.TOPRIGHT) { enc.width = xa - (ox - ow / 2); enc.height = oy + oh / 2 - ya; enc.cx = xa - enc.width / 2; enc.cy = ya + enc.height / 2; enc.calcEdges(); curDiag.changed = true; repaint(); return; } if (enc.corner == Corner.BOTTOMRIGHT) { enc.width = xa - (ox - ow / 2); enc.height = ya - (oy - oh / 2); enc.cx = xa - enc.width / 2; enc.cy = ya - enc.height / 2; enc.calcEdges(); curDiag.changed = true; repaint(); return; } //curDiag.changed = true; //repaint(); //return; } if (blockSelForDragging != null) { // set in mousePressed if (curDiag.clickToGrid && Math.abs(xa - oldx) < 6 && Math.abs(ya - oldy) < 6 || // do not respond Math.abs(xa - blockSelForDragging.cx) > 100 || // to small twitches Math.abs(ya - blockSelForDragging.cy) > 100) // or big twitches! return; Block block = blockSelForDragging; displayAlignmentLines(block); for (Arrow arrow : curDiag.arrows.values()) { if (arrow.fromId == block.id) { arrow.fromX += xa - oldx; arrow.fromY += ya - oldy; } if (arrow.toId == block.id && !arrow.endsAtLine) { arrow.toX += xa - oldx; arrow.toY += ya - oldy; } } block.cx += xa - oldx; block.cy += ya - oldy; block.calcEdges(); if (arrowRoot != null && arrowRoot.b == block) { arrowRoot.x += xa - oldx; arrowRoot.y += ya - oldy; } if (block instanceof Enclosure) { Enclosure enc = (Enclosure) block; if (enc.llb != null) { for (Block bk : enc.llb) { bk.cx += xa - oldx; bk.cy += ya - oldy; bk.calcEdges(); } } if (enc.lla != null) { for (Arrow a : enc.lla) { a.fromX += xa - oldx; a.fromY += ya - oldy; a.toX += xa - oldx; a.toY += ya - oldy; if (a.bends != null) for (Bend bd : a.bends) { bd.x += xa - oldx; bd.y += ya - oldy; } } } } oldx = xa; oldy = ya; curDiag.changed = true; repaint(); // block.calcEdges(); } if (curDiag.currentArrow != null) { // this ensures the line // stays visible curDiag.currentArrow.toX = xa; curDiag.currentArrow.toY = ya; curDiag.changed = true; } repaint(); } public void mouseReleased(MouseEvent e) { int i = jtp.getSelectedIndex(); if (i == -1) return; ButtonTabComponent b = (ButtonTabComponent) jtp .getTabComponentAt(i); curDiag = b.diag; int x = (int) e.getX(); int y = (int) e.getY(); if (curDiag.jpm != null) { curDiag.jpm.setVisible(false); curDiag.jpm = null; frame.repaint(); return; } x = (int) Math.round(x / scalingFactor); y = (int) Math.round(y / scalingFactor); int xa, ya; Side side = null; Point p2 = new Point(x, y); p2 = gridAlign(p2); xa = (int) p2.getX(); ya = (int) p2.getY(); if (curDiag.area.contains(x, y) && panSwitch) { frame.setCursor(openPawCursor); repaint(); return; } if (curDiag.currentArrow == null) { xa = curx; // used for bend dragging ya = cury; } if (e.getClickCount() == 2 || !leftButton) { // enclSelForDragging = null; // arrowEndForDragging = null; // bendForDragging = null; if (blockSelForDragging != null) { selBlock = blockSelForDragging; // this tests if mouse has moved (approximately) - ignore // small twitches and also big jumps! if (between(mousePressedX, x - 4 * scalingFactor, x + 4 * scalingFactor) && between(mousePressedY, y - 4 * scalingFactor, y + 4 * scalingFactor) || Math.abs(mousePressedX - x) > 100 || Math.abs(mousePressedY - y) > 100) { // if it was a small move, or a big jump, just get // subnet, or display options if (leftButton && blockSelForDragging.isSubnet) { if (blockSelForDragging.diagramFileName == null) { MyOptionPane.showMessageDialog(null, "No subnet diagram assigned", MyOptionPane.INFORMATION_MESSAGE); } else { File f = new File( blockSelForDragging.diagramFileName); Diagram saveCurDiag = curDiag; int i2 = curDiag.diagramIsOpen(f.getAbsolutePath()); if (i2 > -1 ){ ButtonTabComponent b2 = (ButtonTabComponent) jtp .getTabComponentAt(i); curDiag = b2.diag; //curDiag.tabNum = i; jtp.setSelectedIndex(i); repaint(); return; } if (null == openAction(f.getAbsolutePath())) curDiag = saveCurDiag; curDiag.parent = blockSelForDragging; } } else { blockSelForDragging.buildBlockPopupMenu(); //if (frame == null) // curDiag = new Diagram(driver); curDiag = blockSelForDragging.diag; int j; if (curDiag == null) j = 1; else if (curDiag.jpm == null) j = 1; curDiag.jpm.show(frame, curDiag.xa + 100, curDiag.ya + 100); } // blockSelForDragging = null; } // else { curDiag.changed = true; //} repaint(); //return; } } if (arrowEndForDragging != null) { curDiag.currentArrow = null; curDiag.foundBlock = null; // curDiag.changed = true; Arrow arr = arrowEndForDragging; for (Block block : curDiag.blocks.values()) { if (arr.tailMarked) { arr.fromId = -1; if (arr.touches(block, arr.fromX, arr.fromY)) { arr.fromId = block.id; break; } } if (arr.headMarked) { arr.toId = -1; if (arrowEndForDragging.touches(block, arrowEndForDragging.toX, arrowEndForDragging.toY)) { arr.toId = block.id; break; } } } arr.tailMarked = false; arr.headMarked = false; arrowEndForDragging = null; curDiag.changed = true; repaint(); return; } if (bendForDragging != null) { bendForDragging.marked = false; bendForDragging = null; curDiag.changed = true; repaint(); return; } if (blockSelForDragging != null) { // if (Math.abs(xa - oldx) < 4 && Math.abs(ya - oldy) < 4) // do // not respond to small twitches // return; selBlock = blockSelForDragging; int savex = blockSelForDragging.cx; int savey = blockSelForDragging.cy; if (blockSelForDragging.hNeighbour != null) { if (curDiag.clickToGrid) { blockSelForDragging.cy = blockSelForDragging.hNeighbour.cy; blockSelForDragging.calcEdges(); } blockSelForDragging.hNeighbour = null; } if (blockSelForDragging.vNeighbour != null) { if (curDiag.clickToGrid) { blockSelForDragging.cx = blockSelForDragging.vNeighbour.cx; blockSelForDragging.calcEdges(); } blockSelForDragging.vNeighbour = null; } // boolean atFromEnd = true; for (Arrow arrow : curDiag.arrows.values()) { if (arrow.fromId == blockSelForDragging.id) { // arrow.adjust(atFromEnd); // arrow.adjustSlope(fromEnd); arrow.fromX += blockSelForDragging.cx - savex; arrow.fromY += blockSelForDragging.cy - savey; } if (arrow.toId == blockSelForDragging.id && !arrow.endsAtLine) { // arrow.adjust(!atFromEnd); // arrow.adjustSlope(!fromEnd); arrow.toX += blockSelForDragging.cx - savex; arrow.toY += blockSelForDragging.cy - savey; } } if (blockSelForDragging instanceof Enclosure) { Enclosure enc = (Enclosure) blockSelForDragging; if (enc.llb != null) enc.llb = null; if (enc.lla != null) enc.lla = null; enc.draggingContents = false; } // blockSelForDragging = null; repaint(); return; } if (blockSelForDragging != null && blockSelForDragging instanceof Enclosure) { ((Enclosure) blockSelForDragging).corner = null; blockSelForDragging = null; curDiag.changed = true; repaint(); return; } curDiag.foundBlock = null; if (curDiag.currentArrow == null) { // Look for a line to detect - for deletion, etc. - logic to end arrow at a line comes in a later section... curDiag.foundArrow = null; // if (!leftButton) { for (Arrow arrow : curDiag.arrows.values()) { if (curDiag.matchArrow(xa, ya, arrow)) { curDiag.foundArrow = arrow; break; } } selArrow = curDiag.foundArrow; // selBlockP = null; // curDiag.changed = true; if (curDiag.foundArrow != null) { Arrow arr = curDiag.foundArrow; if (arr.endsAtLine || arr.endsAtBlock) { if (curDiag.findArrowCrossing) { processSubnetPort(arr); repaint(); return; } arr.buildArrowPopupMenu(); curDiag = arr.diag; // curDiag.currentArrow.lastX = xa; // curDiag.currentArrow.lastY = ya; curDiag.jpm.show(e.getComponent(), xa, ya); repaint(); return; } } else if (curDiag.findArrowCrossing) MyOptionPane.showMessageDialog(frame, "No arrow detected"); curDiag.findArrowCrossing = false; // } // if (curDiag.currentArrow == null) { curDiag.foundBlock = null; // Check if we are within a block for (Block block : curDiag.blocks.values()) { // block.calcEdges(); if (!(block instanceof Enclosure)) { if (between(xa, block.cx - block.width / 2, block.cx + block.width / 2) && between(ya, block.cy - block.height / 2, block.cy + block.height / 2)) { curDiag.foundBlock = block; selBlock = block; selArrow = null; // block.x = xa; // block.y = ya; break; } } else { // if it is an enclosure block int hh = gFontHeight; if (between(xa, block.cx - block.width / 2 + block.width / 5, block.cx + block.width / 2 - block.width / 5) && between(ya, block.cy - block.height / 2 - hh, block.cy - block.height / 2 + hh / 2)) { curDiag.foundBlock = block; selBlock = block; selArrow = null; // block.x = xa; // block.y = ya; break; } } } // Didn't find a block, so we can create a new block - // block must not overlap x=0 or y=0 // use right button // if (left) // return; curDiag.xa = xa; curDiag.ya = ya; if (!(blockType.equals("")) && null != createBlock(blockType)) curDiag.changed = true; frame.repaint(); // repaint(); repaint(); return; } // curDiag.currentArrow is not null.... // check for end of arrow curDiag.foundBlock = null; FoundPoint fp = findArrowStart(xa, ya); if (fp != null) { curDiag.foundBlock = fp.b; side = fp.side; } if (curDiag.foundBlock != null // && leftButton ) { if (between(curDiag.currentArrow.fromX, x - 4 * scalingFactor, x + 4 * scalingFactor) && between(curDiag.currentArrow.fromY, y - 4 * scalingFactor, y + 4 * scalingFactor)) return; if (curDiag.foundBlock.id == curDiag.currentArrow.fromId) { if (MyOptionPane.NO_OPTION == MyOptionPane.showConfirmDialog( frame, "Connecting arrow to originating block is deadlock-prone - do anyway?", "Allow?", MyOptionPane.YES_NO_OPTION)) { Integer aid = new Integer(curDiag.currentArrow.id); curDiag.arrows.remove(aid); curDiag.foundBlock = null; curDiag.currentArrow = null; repaint(); return; } } boolean OK = true; Block from = curDiag.blocks .get(new Integer(curDiag.currentArrow.fromId)); if ((curDiag.foundBlock instanceof ProcessBlock || curDiag.foundBlock instanceof ExtPortBlock) && !(from instanceof IIPBlock)) { if (side == Side.BOTTOM) { int answer = MyOptionPane.showConfirmDialog(frame, "Connect arrow to bottom of block?", "Please choose one", MyOptionPane.YES_NO_OPTION); if (answer != MyOptionPane.YES_OPTION) OK = false; } if (side == Side.RIGHT) { int answer = MyOptionPane.showConfirmDialog(frame, "Connect arrow to righthand side?", "Please choose one", MyOptionPane.YES_NO_OPTION); if (answer != MyOptionPane.YES_OPTION) OK = false; } } if (!OK) { // MyOptionPane.showMessageDialog(frame, // "Cannot end an arrow here"); Integer aid = new Integer(curDiag.currentArrow.id); curDiag.arrows.remove(aid); curDiag.foundBlock = null; curDiag.currentArrow = null; repaint(); return; } Arrow a = curDiag.currentArrow; a.endsAtBlock = true; a.toId = curDiag.foundBlock.id; if (xa != curx) { // make sure t not // zero! double s = ya - a.lastY; double t = xa - a.lastX; s = s / t; if (Math.abs(s) < FORCE_HORIZONTAL) // force horizontal ya = a.lastY; if (Math.abs(s) > FORCE_VERTICAL) // force vertical xa = a.lastX; } a.toX = xa; a.toY = ya; // a.toSide = side; from = curDiag.blocks.get(new Integer(a.fromId)); Block to = curDiag.blocks.get(new Integer(a.toId)); if (from != null && (from instanceof ProcessBlock || from instanceof ExtPortBlock || from instanceof Enclosure || from instanceof IIPBlock) && (a.endsAtLine || (to != null && (to instanceof ProcessBlock || to instanceof ExtPortBlock || to instanceof Enclosure)))) { if (!(from instanceof FileBlock || from instanceof PersonBlock || from instanceof ReportBlock || from instanceof LegendBlock || to instanceof FileBlock || to instanceof PersonBlock || to instanceof ReportBlock || to instanceof LegendBlock ) ) { if (!(from instanceof IIPBlock) && (a.upStreamPort == null || a.upStreamPort.trim().equals(""))) a.upStreamPort = "OUT"; if (!a.endsAtLine && (a.downStreamPort == null || a.downStreamPort.trim().equals(""))) a.downStreamPort = "IN"; } } Boolean error = false; if (to instanceof IIPBlock && from instanceof ProcessBlock) { a.reverseDirection(); // MyOptionPane // .showMessageDialog(frame, // "Direction of arrow has been reversed"); } if (from instanceof ExtPortBlock && (from.type .equals(Block.Types.EXTPORT_OUT_BLOCK) || from.type.equals(Block.Types.EXTPORT_OUTIN_BLOCK) && a.fromX < from.cx)) error = true; else if (to instanceof ExtPortBlock && (to.type .equals(Block.Types.EXTPORT_IN_BLOCK) || to.type.equals(Block.Types.EXTPORT_OUTIN_BLOCK) && a.toX > to.cx)) error = true; if (!a.checkSides()) error = true; if (error) { MyOptionPane.showMessageDialog(frame, "Arrow attached to one or both wrong side(s) of blocks", MyOptionPane.WARNING_MESSAGE); Integer aid = new Integer(a.id); curDiag.arrows.remove(aid); } else { curDiag.changed = true; // checkCompatibility(a); } curDiag.foundBlock = null; curDiag.currentArrow = null; // curDiag.changed = true; repaint(); return; } // currentDiag.foundBlock must be null // see if we can end an arrow on a line or line segment if (curDiag.currentArrow != null && curDiag.foundBlock == null // && leftButton ) { curDiag.foundArrow = null; Arrow a = curDiag.currentArrow; for (Arrow arrow : curDiag.arrows.values()) { if (arrow != a && curDiag.matchArrow(xa, ya, arrow)) curDiag.foundArrow = arrow; } if (curDiag.foundArrow != null) { // && leftButton if (x != curx) { double s = y - a.lastY; double t = x - a.lastX; s = s / t; if (Math.abs(s) < FORCE_HORIZONTAL) // force horizontal y = curDiag.currentArrow.lastY; if (Math.abs(s) > FORCE_VERTICAL) // force vertical x = curDiag.currentArrow.lastX; } a.toX = x; // ???????????? // curDiag.currentArrow.toY = y; //???????????? a.toY = y; curDiag.currentArrow.endsAtLine = true; // use id of target line, not of target block curDiag.currentArrow.toId = curDiag.foundArrow.id; Block from = curDiag.blocks.get(new Integer(a.fromId)); // Block to = curDiag.blocks.get(new Integer( // a.toId)); Arrow a2 = curDiag.currentArrow.findArrowEndingAtBlock(); Block to = curDiag.blocks.get(new Integer(a2.toId)); if (from != null && (from instanceof ProcessBlock || from instanceof ExtPortBlock || from instanceof Enclosure || from instanceof IIPBlock) && (a.endsAtLine || (to != null && (to instanceof ProcessBlock || to instanceof ExtPortBlock || to instanceof Enclosure)))) { if (!(from instanceof FileBlock || from instanceof PersonBlock || from instanceof ReportBlock || from instanceof LegendBlock || to instanceof FileBlock || to instanceof PersonBlock || to instanceof ReportBlock || to instanceof LegendBlock ) ) { if (!(from instanceof IIPBlock) && (a.upStreamPort == null || a.upStreamPort.trim().equals(""))) a.upStreamPort = "OUT"; if (!a.endsAtLine && (a.downStreamPort == null || a.downStreamPort.trim().equals(""))) a.downStreamPort = "IN"; if (a.endsAtLine && (a2.downStreamPort == null || a2.downStreamPort.trim().equals(""))) a2.downStreamPort = "IN"; } } a.downStreamPort = a2.downStreamPort; // Block from = curDiag.blocks.get(new Integer( // a.fromId)); // Arrow a2 = curDiag.currentArrow.findTerminalArrow(); // to = curDiag.blocks.get(new Integer(a2.toId)); if (to == from) { if (MyOptionPane.NO_OPTION == MyOptionPane .showConfirmDialog(frame, "Connecting arrow to originating block is deadlock-prone - do anyway?", "Allow?", MyOptionPane.YES_NO_OPTION)) { Integer aid = new Integer(curDiag.currentArrow.id); curDiag.arrows.remove(aid); curDiag.foundBlock = null; curDiag.currentArrow = null; repaint(); return; } } boolean error = true; if (from instanceof ExtPortBlock && from.type.equals(Block.Types.EXTPORT_OUT_BLOCK)) MyOptionPane.showMessageDialog(frame, "Arrow in wrong direction", MyOptionPane.ERROR_MESSAGE); else if (to instanceof ExtPortBlock && to.type.equals(Block.Types.EXTPORT_IN_BLOCK)) MyOptionPane.showMessageDialog(frame, "Arrow in wrong direction", MyOptionPane.ERROR_MESSAGE); else error = false; if (error) { Integer aid = new Integer(curDiag.currentArrow.id); curDiag.arrows.remove(aid); } else { curDiag.changed = true; // checkCompatibility(curDiag.currentArrow); if (to != null) { if (side == Side.TOP) curDiag.currentArrow.toY = to.cy - to.height / 2; else if (side == Side.BOTTOM) curDiag.currentArrow.toY = to.cy + to.height / 2; else if (side == Side.LEFT) curDiag.currentArrow.toX = to.cx - to.width / 2; else if (side == Side.RIGHT) curDiag.currentArrow.toX = to.cx + to.width / 2; } } curDiag.currentArrow = null; repaint(); return; } // else if (leftButton) { // currentDiag.foundArrow is null, so // we may // have a // bend if (curDiag.currentArrow != null) { if (!(between(xa, curDiag.currentArrow.toX - 4, curDiag.currentArrow.toX + 4) && between(ya, curDiag.currentArrow.toY - 4, curDiag.currentArrow.toY + 4))) { // curDiag.currentArrow.toX = xa; // curDiag.currentArrow.toY = ya; // } // else { Integer aid = new Integer(curDiag.currentArrow.id); curDiag.arrows.remove(aid); curDiag.foundBlock = null; curDiag.currentArrow = null; repaint(); return; } // repaint(); } if (curDiag.currentArrow.bends == null) { curDiag.currentArrow.bends = new LinkedList<Bend>(); } x = xa; y = ya; if (xa != curDiag.currentArrow.lastX) { double s = ya - curDiag.currentArrow.lastY; double t = xa - curDiag.currentArrow.lastX; s = s / t; if (Math.abs(s) < FORCE_HORIZONTAL) // force horizontal ya = curDiag.currentArrow.lastY; if (Math.abs(s) > FORCE_VERTICAL) // force vertical xa = curDiag.currentArrow.lastX; } Bend bend = new Bend(xa, ya); curDiag.currentArrow.bends.add(bend); curDiag.currentArrow.lastX = x; curDiag.currentArrow.lastY = y; curDiag.currentArrow.toX = x; curDiag.currentArrow.toY = y; curDiag.changed = true; repaint(); // return; // } } } public void mouseClicked(MouseEvent arg0) { // do nothing } } }